@peter.prib/renderengine 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +203 -2
- package/REFERENCE.md +2198 -0
- package/dist/renderengine-workspace.umd.js +46905 -0
- package/dist/renderengine.umd.js +42223 -0
- package/examples/archimate.html +66 -0
- package/examples/diagram-editor.html +51 -0
- package/package.json +65 -4
- package/src/BaseRenderer.js +57 -0
- package/src/CanvasRenderer.js +194 -0
- package/src/Mat4.js +111 -0
- package/src/OrbitCamera.js +57 -0
- package/src/RendererFactory.js +50 -0
- package/src/SVGRenderer.js +439 -0
- package/src/archimate.js +723 -0
- package/src/archimateArchiFormat.js +1693 -0
- package/src/archimateArchiTypes.js +72 -0
- package/src/archimateArchive.js +140 -0
- package/src/archimateCSV.js +127 -0
- package/src/archimateDrawio.js +182 -0
- package/src/archimateExchangeFormat.js +546 -0
- package/src/archimateRelationshipTable.js +93 -0
- package/src/archimateSpecializations.js +161 -0
- package/src/chartCatalog.js +589 -0
- package/src/charting/ArchimateDiagramEditor.js +1624 -0
- package/src/charting/ArchimateSpecializationSelector.js +134 -0
- package/src/charting/Axis.js +68 -0
- package/src/charting/CameraSeeder.js +30 -0
- package/src/charting/CatalogDialog.js +92 -0
- package/src/charting/Chart.js +37 -0
- package/src/charting/Chart3D.js +99 -0
- package/src/charting/ChartBox.js +80 -0
- package/src/charting/ChartData.js +27 -0
- package/src/charting/ChartRegistry.js +76 -0
- package/src/charting/CheckboxTreeSelector.js +304 -0
- package/src/charting/ColorField.js +107 -0
- package/src/charting/ColorPalette.js +88 -0
- package/src/charting/CommandHistory.js +176 -0
- package/src/charting/DataFilter.js +52 -0
- package/src/charting/Diagram.js +36 -0
- package/src/charting/Diagram3D.js +29 -0
- package/src/charting/DiagramClipboard.js +31 -0
- package/src/charting/DiagramEditor.js +3330 -0
- package/src/charting/DiagramEditorCommand.js +110 -0
- package/src/charting/DiagramEditorCommands.js +237 -0
- package/src/charting/DiagramEditorEdgeCommands.js +142 -0
- package/src/charting/DiagramEditorState.js +98 -0
- package/src/charting/DiagramRegistry.js +86 -0
- package/src/charting/DiagramTypeRegistry.js +326 -0
- package/src/charting/DiagramViewPropertiesDialog.js +46 -0
- package/src/charting/Edge.js +113 -0
- package/src/charting/ErrorBars.js +37 -0
- package/src/charting/FilterSystem.js +285 -0
- package/src/charting/FindReplaceDialog.js +139 -0
- package/src/charting/FormDialog.js +385 -0
- package/src/charting/Gauge.js +58 -0
- package/src/charting/Hierarchy.js +175 -0
- package/src/charting/HintPanel.js +86 -0
- package/src/charting/ImageSelector.js +148 -0
- package/src/charting/InteractionManager.js +725 -0
- package/src/charting/Legend.js +58 -0
- package/src/charting/MenuBar.js +62 -0
- package/src/charting/ModelFileFormat.js +115 -0
- package/src/charting/OrbitControls.js +77 -0
- package/src/charting/Palette.js +119 -0
- package/src/charting/PopupMenu.js +117 -0
- package/src/charting/PropertiesPanel.js +155 -0
- package/src/charting/PropertyListEditor.js +96 -0
- package/src/charting/PropertyLog.js +92 -0
- package/src/charting/SettingsCascade.js +93 -0
- package/src/charting/SettingsDialog.js +53 -0
- package/src/charting/SettingsManager.js +179 -0
- package/src/charting/SettingsViewPropertiesDialog.js +58 -0
- package/src/charting/ShapePaths.js +27 -0
- package/src/charting/Statistics.js +134 -0
- package/src/charting/TemplateCatalog.js +59 -0
- package/src/charting/TemplateLibrary.js +103 -0
- package/src/charting/TextStyle.js +168 -0
- package/src/charting/ViewFit.js +55 -0
- package/src/charting/ViewMenu.js +70 -0
- package/src/charting/ViewPropertiesDialog.js +77 -0
- package/src/charting/ViewTabStrip.js +81 -0
- package/src/charting/archimate/ArchiFileFormat.js +32 -0
- package/src/charting/archimate/ArchimateCanvasEditor.js +815 -0
- package/src/charting/archimate/ArchimateCsvFileFormat.js +35 -0
- package/src/charting/archimate/ArchimateEdge.js +137 -0
- package/src/charting/archimate/ArchimateElementTemplate.js +195 -0
- package/src/charting/archimate/ArchimatePalette.js +102 -0
- package/src/charting/archimate/CsvImportDialog.js +105 -0
- package/src/charting/archimate/CustomViewpoints.js +74 -0
- package/src/charting/archimate/DerivedEdge.js +29 -0
- package/src/charting/archimate/DrawioFileFormat.js +24 -0
- package/src/charting/archimate/ElementFilterRule.js +21 -0
- package/src/charting/archimate/ExchangeFileFormat.js +28 -0
- package/src/charting/archimate/ViewGroupTemplate.js +137 -0
- package/src/charting/archimate/ViewLineEdge.js +84 -0
- package/src/charting/archimate/ViewpointRule.js +45 -0
- package/src/charting/archimate/archimateFileFormats.js +12 -0
- package/src/charting/archimate/archimateNames.js +5 -0
- package/src/charting/archimate/csvMapping.js +122 -0
- package/src/charting/archimate/elementMenuItems.js +32 -0
- package/src/charting/archimate/elementProperties.js +146 -0
- package/src/charting/archimate/elementTypeChoices.js +7 -0
- package/src/charting/archimate/elementTypeGroups.js +19 -0
- package/src/charting/archimate/index.js +17 -0
- package/src/charting/archimate/specializationCatalogDialog.js +64 -0
- package/src/charting/archimate/typeGlyph.js +29 -0
- package/src/charting/arrangement/Arrangement.js +112 -0
- package/src/charting/arrangement/ArrangementCommand.js +29 -0
- package/src/charting/arrangement/BackgroundCommand.js +41 -0
- package/src/charting/arrangement/BackgroundGroup.js +18 -0
- package/src/charting/arrangement/GroupCommand.js +46 -0
- package/src/charting/arrangement/ItemGroup.js +62 -0
- package/src/charting/arrangement/LockCommand.js +32 -0
- package/src/charting/arrangement/UngroupCommand.js +27 -0
- package/src/charting/arrangement/alignment.js +88 -0
- package/src/charting/arrangement/arrangeMenuItems.js +25 -0
- package/src/charting/arrangement/index.js +11 -0
- package/src/charting/arrangement/layouts.js +233 -0
- package/src/charting/canvas/ArchiHint.js +78 -0
- package/src/charting/canvas/CanvasBoxKind.js +39 -0
- package/src/charting/canvas/CanvasPalette.js +49 -0
- package/src/charting/canvas/CanvasTemplateLibrary.js +61 -0
- package/src/charting/canvas/CanvasTemplateMenu.js +151 -0
- package/src/charting/canvas/EditHintCommand.js +28 -0
- package/src/charting/canvas/canvasBoxKinds.js +27 -0
- package/src/charting/canvas/canvasBoxMenuItems.js +40 -0
- package/src/charting/canvas/defaultCanvasTemplates.js +186 -0
- package/src/charting/canvas/diagramBoxKinds.js +12 -0
- package/src/charting/canvas/hintMenuItems.js +49 -0
- package/src/charting/charts/ArcGauge.js +55 -0
- package/src/charting/charts/AreaChart.js +71 -0
- package/src/charting/charts/BarChart.js +80 -0
- package/src/charting/charts/BarChart3D.js +56 -0
- package/src/charting/charts/BarChart3DOrbit.js +53 -0
- package/src/charting/charts/BarChartBase.js +70 -0
- package/src/charting/charts/BarGauge.js +42 -0
- package/src/charting/charts/BoxPlotChart.js +41 -0
- package/src/charting/charts/BubbleChart.js +99 -0
- package/src/charting/charts/BubbleChart3D.js +78 -0
- package/src/charting/charts/BulletGauge.js +87 -0
- package/src/charting/charts/CalendarHeatmapChart.js +204 -0
- package/src/charting/charts/CandlestickChart.js +54 -0
- package/src/charting/charts/ChordDiagram.js +130 -0
- package/src/charting/charts/DensityChart.js +73 -0
- package/src/charting/charts/DialGauge.js +65 -0
- package/src/charting/charts/DonutChart.js +15 -0
- package/src/charting/charts/FunnelChart.js +47 -0
- package/src/charting/charts/GanttChart.js +201 -0
- package/src/charting/charts/GaugeChart.js +175 -0
- package/src/charting/charts/GeoMapChart.js +146 -0
- package/src/charting/charts/GroupedBarChart.js +88 -0
- package/src/charting/charts/GroupedDistributionChart.js +70 -0
- package/src/charting/charts/HeatmapChart.js +80 -0
- package/src/charting/charts/HierarchyChart.js +39 -0
- package/src/charting/charts/HistogramChart.js +45 -0
- package/src/charting/charts/KpiTile.js +72 -0
- package/src/charting/charts/LagPlotChart.js +41 -0
- package/src/charting/charts/LineChart.js +124 -0
- package/src/charting/charts/MultiRingGauge.js +54 -0
- package/src/charting/charts/OutlineChart.js +95 -0
- package/src/charting/charts/ParallelCoordinatesChart.js +130 -0
- package/src/charting/charts/PieChart.js +56 -0
- package/src/charting/charts/PipeChart.js +88 -0
- package/src/charting/charts/PopulationPyramidChart.js +106 -0
- package/src/charting/charts/QQPlotChart.js +64 -0
- package/src/charting/charts/RadarChart.js +76 -0
- package/src/charting/charts/RadialBarChart.js +96 -0
- package/src/charting/charts/RingGauge.js +23 -0
- package/src/charting/charts/SankeyDiagram.js +174 -0
- package/src/charting/charts/ScatterChart.js +104 -0
- package/src/charting/charts/StackedAreaChart.js +15 -0
- package/src/charting/charts/StackedBarChart.js +33 -0
- package/src/charting/charts/StackedBarChart3DOrbit.js +58 -0
- package/src/charting/charts/StreamGraphChart.js +131 -0
- package/src/charting/charts/SunburstChart.js +57 -0
- package/src/charting/charts/ThermometerGauge.js +43 -0
- package/src/charting/charts/TreemapChart.js +54 -0
- package/src/charting/charts/ViolinChart.js +37 -0
- package/src/charting/charts/WaterfallChart.js +66 -0
- package/src/charting/charts/WordCloudChart.js +104 -0
- package/src/charting/diagramModel/AddViewCommand.js +33 -0
- package/src/charting/diagramModel/DiagramModel.js +39 -0
- package/src/charting/diagramModel/DiagramModelSearch.js +22 -0
- package/src/charting/diagramModel/DiagramView.js +50 -0
- package/src/charting/diagramModel/ModelHistory.js +43 -0
- package/src/charting/diagramModel/ModelReport.js +153 -0
- package/src/charting/diagramModel/ModelSearch.js +223 -0
- package/src/charting/diagramModel/RemoveViewCommand.js +25 -0
- package/src/charting/diagramModel/RenameViewCommand.js +21 -0
- package/src/charting/diagramModel/ReplaceTextCommand.js +25 -0
- package/src/charting/diagramModel/ViewSetChecker.js +34 -0
- package/src/charting/diagramModel/ViewSetModel.js +243 -0
- package/src/charting/diagramModel/index.js +6 -0
- package/src/charting/diagramModel/nameTransforms.js +29 -0
- package/src/charting/diagrams/ArchimateCommands.js +141 -0
- package/src/charting/diagrams/ArchimateDiagram.js +263 -0
- package/src/charting/diagrams/ArchimateModel.js +1155 -0
- package/src/charting/diagrams/ArchimateModelChecker.js +125 -0
- package/src/charting/diagrams/ArchimateModelReport.js +128 -0
- package/src/charting/diagrams/ArchimateModelSearch.js +41 -0
- package/src/charting/diagrams/ArchimateValidator.js +357 -0
- package/src/charting/diagrams/CanvasView.js +112 -0
- package/src/charting/diagrams/ContextMenu.js +37 -0
- package/src/charting/diagrams/DataModelDiagram.js +86 -0
- package/src/charting/diagrams/DataModelRelationshipStrategy.js +38 -0
- package/src/charting/diagrams/DerivedRelationships.js +102 -0
- package/src/charting/diagrams/EbnfDiagram.js +39 -0
- package/src/charting/diagrams/EdgeGeometry.js +553 -0
- package/src/charting/diagrams/EditViewItemCommand.js +128 -0
- package/src/charting/diagrams/ElementInstance.js +157 -0
- package/src/charting/diagrams/GraphDiagram.js +1340 -0
- package/src/charting/diagrams/GraphDiagram3D.js +152 -0
- package/src/charting/diagrams/GraphMetrics.js +81 -0
- package/src/charting/diagrams/GridOverlay.js +137 -0
- package/src/charting/diagrams/ImportRowsCommand.js +62 -0
- package/src/charting/diagrams/LabelHelper.js +108 -0
- package/src/charting/diagrams/MergeElementsCommand.js +101 -0
- package/src/charting/diagrams/NestInstanceCommand.js +34 -0
- package/src/charting/diagrams/NodeGeometry.js +158 -0
- package/src/charting/diagrams/PlaceItemsCommand.js +77 -0
- package/src/charting/diagrams/RadialLayout.js +101 -0
- package/src/charting/diagrams/RelationshipInstance.js +93 -0
- package/src/charting/diagrams/RemoveGroupFromViewCommand.js +28 -0
- package/src/charting/diagrams/RemoveLineCommand.js +27 -0
- package/src/charting/diagrams/ShowElementCommand.js +43 -0
- package/src/charting/diagrams/SvgCoordinate.js +17 -0
- package/src/charting/diagrams/SvgZoom.js +127 -0
- package/src/charting/diagrams/Tooltip.js +62 -0
- package/src/charting/diagrams/ViewConnectionInstance.js +102 -0
- package/src/charting/diagrams/ViewObjectInstance.js +56 -0
- package/src/charting/diagrams/commands/AddEdgeCommand.js +34 -0
- package/src/charting/diagrams/commands/AddNodeCommand.js +28 -0
- package/src/charting/diagrams/commands/AddWaypointCommand.js +27 -0
- package/src/charting/diagrams/commands/CreateFolderCommand.js +27 -0
- package/src/charting/diagrams/commands/DeleteEdgeCommand.js +30 -0
- package/src/charting/diagrams/commands/DeleteFolderCommand.js +47 -0
- package/src/charting/diagrams/commands/DeleteNodeCommand.js +35 -0
- package/src/charting/diagrams/commands/DeleteWaypointCommand.js +24 -0
- package/src/charting/diagrams/commands/GraphCommand.js +65 -0
- package/src/charting/diagrams/commands/InvertEdgeCommand.js +24 -0
- package/src/charting/diagrams/commands/MoveNodeCommand.js +44 -0
- package/src/charting/diagrams/commands/MoveWaypointCommand.js +27 -0
- package/src/charting/diagrams/commands/RenameEdgeCommand.js +23 -0
- package/src/charting/diagrams/commands/RenameFolderCommand.js +31 -0
- package/src/charting/diagrams/commands/RenameNodeCommand.js +27 -0
- package/src/charting/diagrams/commands/ResizeNodeCommand.js +46 -0
- package/src/charting/diagrams/commands/UpdateEdgeSideCommand.js +40 -0
- package/src/charting/diagrams/commands/index.js +17 -0
- package/src/charting/diagrams/duplicates.js +49 -0
- package/src/charting/diagrams/nesting.js +30 -0
- package/src/charting/diagrams/roadmap.js +77 -0
- package/src/charting/edgeMarkers/ArrowMarker.js +15 -0
- package/src/charting/edgeMarkers/CircleMarker.js +13 -0
- package/src/charting/edgeMarkers/CrowsFootMarker.js +16 -0
- package/src/charting/edgeMarkers/DiamondMarker.js +15 -0
- package/src/charting/edgeMarkers/EdgeMarker.js +34 -0
- package/src/charting/edgeMarkers/HalfArrowMarker.js +8 -0
- package/src/charting/edgeMarkers/HollowDiamondMarker.js +18 -0
- package/src/charting/edgeMarkers/HollowTriangleMarker.js +18 -0
- package/src/charting/edgeMarkers/OpenArrowMarker.js +17 -0
- package/src/charting/edgeMarkers/index.js +27 -0
- package/src/charting/edgeStyle/EdgeStyleCascade.js +22 -0
- package/src/charting/edgeStyle/EdgeStyleDialog.js +51 -0
- package/src/charting/edgeStyle/EdgeStyleSchema.js +43 -0
- package/src/charting/edgeStyle/SetStyleCommand.js +12 -0
- package/src/charting/edgeStyle/index.js +4 -0
- package/src/charting/emphasis/EmphasisRule.js +42 -0
- package/src/charting/emphasis/HighlightRule.js +24 -0
- package/src/charting/gauges/ArcTrack.js +51 -0
- package/src/charting/gauges/GaugeAnimation.js +51 -0
- package/src/charting/gauges/GaugeBands.js +48 -0
- package/src/charting/gauges/GaugeScale.js +87 -0
- package/src/charting/gauges/GaugeTrack.js +44 -0
- package/src/charting/gauges/GaugeValue.js +61 -0
- package/src/charting/gauges/HorizontalTrack.js +14 -0
- package/src/charting/gauges/LinearTrack.js +29 -0
- package/src/charting/gauges/Sparkline.js +42 -0
- package/src/charting/gauges/VerticalTrack.js +17 -0
- package/src/charting/glyphs/ArrowGlyph.js +21 -0
- package/src/charting/glyphs/BatteryGlyph.js +18 -0
- package/src/charting/glyphs/ChevronGlyph.js +18 -0
- package/src/charting/glyphs/CircleGlyph.js +15 -0
- package/src/charting/glyphs/CloudGlyph.js +19 -0
- package/src/charting/glyphs/ComponentGlyph.js +18 -0
- package/src/charting/glyphs/ConstraintGlyph.js +24 -0
- package/src/charting/glyphs/ContractBoxGlyph.js +10 -0
- package/src/charting/glyphs/CubeGlyph.js +19 -0
- package/src/charting/glyphs/CylinderGlyph.js +19 -0
- package/src/charting/glyphs/DashedDoubleArrowGlyph.js +11 -0
- package/src/charting/glyphs/DeviceGlyph.js +17 -0
- package/src/charting/glyphs/DiamondGlyph.js +17 -0
- package/src/charting/glyphs/DocumentGlyph.js +17 -0
- package/src/charting/glyphs/DoubleArrowGlyph.js +23 -0
- package/src/charting/glyphs/DoubleCircleGlyph.js +24 -0
- package/src/charting/glyphs/EllipseGlyph.js +18 -0
- package/src/charting/glyphs/FactoryGlyph.js +20 -0
- package/src/charting/glyphs/FlagGlyph.js +16 -0
- package/src/charting/glyphs/GapCircleGlyph.js +17 -0
- package/src/charting/glyphs/GearGlyph.js +37 -0
- package/src/charting/glyphs/Glyph.js +98 -0
- package/src/charting/glyphs/GroupingBoxGlyph.js +13 -0
- package/src/charting/glyphs/HalfCircleGlyph.js +22 -0
- package/src/charting/glyphs/HexagonGlyph.js +28 -0
- package/src/charting/glyphs/IconGlyph.js +22 -0
- package/src/charting/glyphs/ImageGlyph.js +16 -0
- package/src/charting/glyphs/JunctionGlyph.js +17 -0
- package/src/charting/glyphs/LollipopGlyph.js +22 -0
- package/src/charting/glyphs/MagnifierGlyph.js +17 -0
- package/src/charting/glyphs/NoteGlyph.js +33 -0
- package/src/charting/glyphs/ObjectBoxGlyph.js +21 -0
- package/src/charting/glyphs/OrJunctionGlyph.js +17 -0
- package/src/charting/glyphs/ParallelogramGlyph.js +20 -0
- package/src/charting/glyphs/PersonGlyph.js +23 -0
- package/src/charting/glyphs/PillGlyph.js +23 -0
- package/src/charting/glyphs/PinGlyph.js +18 -0
- package/src/charting/glyphs/PrincipleGlyph.js +23 -0
- package/src/charting/glyphs/ProductBoxGlyph.js +16 -0
- package/src/charting/glyphs/RectGlyph.js +15 -0
- package/src/charting/glyphs/RoundedBoxGlyph.js +13 -0
- package/src/charting/glyphs/StackGlyph.js +14 -0
- package/src/charting/glyphs/StepsGlyph.js +20 -0
- package/src/charting/glyphs/StickFigureGlyph.js +32 -0
- package/src/charting/glyphs/SystemSoftwareBoxGlyph.js +16 -0
- package/src/charting/glyphs/TabbedBoxGlyph.js +37 -0
- package/src/charting/glyphs/TargetGlyph.js +23 -0
- package/src/charting/glyphs/WavyBoxGlyph.js +17 -0
- package/src/charting/glyphs/WheelGlyph.js +28 -0
- package/src/charting/glyphs/drawGlyph.js +28 -0
- package/src/charting/glyphs/glyphSvg.js +55 -0
- package/src/charting/glyphs/index.js +109 -0
- package/src/charting/modelTree/AnalysisPanel.js +159 -0
- package/src/charting/modelTree/DiagramTabs.js +217 -0
- package/src/charting/modelTree/ModelTree.js +164 -0
- package/src/charting/modelTree/ModelTreePanel.js +914 -0
- package/src/charting/modelTree/TreeBuilder.js +238 -0
- package/src/charting/modelTree/TreeModeRegistry.js +51 -0
- package/src/charting/modelTree/TreeViewMode.js +110 -0
- package/src/charting/modelTree/buildFilterTrees.js +138 -0
- package/src/charting/modelTree/modes/FlatTreeMode.js +46 -0
- package/src/charting/modelTree/modes/LayerGroupedTreeMode.js +62 -0
- package/src/charting/modelTree/modes/TypeGroupedTreeMode.js +60 -0
- package/src/charting/modelTree/treeLayers.js +11 -0
- package/src/charting/report/reportHtml.js +82 -0
- package/src/charting/report/reportViewer.js +118 -0
- package/src/charting/shapes/CircleShape.js +19 -0
- package/src/charting/shapes/PathShape.js +17 -0
- package/src/charting/shapes/RectShape.js +20 -0
- package/src/charting/shapes/Shape.js +20 -0
- package/src/charting/shapes/ShapeFactory.js +23 -0
- package/src/charting/storage/LocalJsonStore.js +43 -0
- package/src/charting/templates/ActorTemplate.js +36 -0
- package/src/charting/templates/BoxTemplate.js +27 -0
- package/src/charting/templates/CircleTemplate.js +18 -0
- package/src/charting/templates/ClassTemplate.js +20 -0
- package/src/charting/templates/CloudTemplate.js +43 -0
- package/src/charting/templates/ComponentTemplate.js +19 -0
- package/src/charting/templates/CylinderTemplate.js +30 -0
- package/src/charting/templates/DataStoreTemplate.js +16 -0
- package/src/charting/templates/DiamondTemplate.js +10 -0
- package/src/charting/templates/DocumentTemplate.js +32 -0
- package/src/charting/templates/EllipseTemplate.js +15 -0
- package/src/charting/templates/FinalStateTemplate.js +12 -0
- package/src/charting/templates/GlyphTemplate.js +47 -0
- package/src/charting/templates/HexagonTemplate.js +17 -0
- package/src/charting/templates/LifelineTemplate.js +20 -0
- package/src/charting/templates/ManualInputTemplate.js +12 -0
- package/src/charting/templates/NoteTemplate.js +23 -0
- package/src/charting/templates/OctagonTemplate.js +7 -0
- package/src/charting/templates/PackageTemplate.js +25 -0
- package/src/charting/templates/ParallelogramTemplate.js +11 -0
- package/src/charting/templates/PentagonTemplate.js +5 -0
- package/src/charting/templates/PolygonTemplate.js +18 -0
- package/src/charting/templates/PredefinedProcessTemplate.js +13 -0
- package/src/charting/templates/RectangleTemplate.js +28 -0
- package/src/charting/templates/RegularPolygonTemplate.js +21 -0
- package/src/charting/templates/RoundedRectangleTemplate.js +5 -0
- package/src/charting/templates/StadiumTemplate.js +8 -0
- package/src/charting/templates/StarTemplate.js +17 -0
- package/src/charting/templates/SwimlaneTemplate.js +18 -0
- package/src/charting/templates/Template.js +208 -0
- package/src/charting/templates/TrapezoidTemplate.js +11 -0
- package/src/charting/templates/TriangleTemplate.js +12 -0
- package/src/charting/templates/index.js +31 -0
- package/src/charting/templates/outline.js +59 -0
- package/src/charting/templates/svg.js +19 -0
- package/src/charting/textToShapes.js +61 -0
- package/src/charting/toolbar/ToolbarButton.js +38 -0
- package/src/charting/toolbar/ToolbarCheckbox.js +31 -0
- package/src/charting/toolbar/ToolbarItem.js +19 -0
- package/src/charting/toolbar/ToolbarMenu.js +36 -0
- package/src/charting/toolbar/ToolbarSelect.js +38 -0
- package/src/charting/toolbar/ToolbarSeparator.js +7 -0
- package/src/charting/toolbar/ToolbarText.js +22 -0
- package/src/charting/toolbar/index.js +8 -0
- package/src/charting/toolbar/pickFile.js +14 -0
- package/src/charting/viewDecorations.js +85 -0
- package/src/charting/zOrder.js +57 -0
- package/src/csvTable.js +61 -0
- package/src/datamodel.js +122 -0
- package/src/datawindow/BoundedWindow.js +36 -0
- package/src/datawindow/FlatDataWindow.js +34 -0
- package/src/datawindow/GraphDataWindow.js +40 -0
- package/src/datawindow/GroupedSampleDataWindow.js +16 -0
- package/src/datawindow/SeriesDataWindow.js +42 -0
- package/src/datawindow/index.js +31 -0
- package/src/diagramCatalog.js +30 -0
- package/src/ebnfDiagram.js +57 -0
- package/src/ebnfParser.js +129 -0
- package/src/exportImage.js +233 -0
- package/src/index.js +2636 -0
- package/src/itIcons.js +84 -0
- package/src/kernelExpr.js +243 -0
- package/src/propertiesDialog.js +463 -0
- package/src/railroadDiagram.js +571 -0
- package/src/treeModeCatalog.js +16 -0
- package/src/workspace/ContextBus.js +79 -0
- package/src/workspace/EditorShell.js +67 -0
- package/src/workspace/Part.js +163 -0
- package/src/workspace/PartFactory.js +49 -0
- package/src/workspace/PartRegistry.js +86 -0
- package/src/workspace/Workspace.js +321 -0
- package/src/workspace/archimateServices.js +33 -0
- package/src/workspace/dom.js +120 -0
- package/src/workspace/index.js +75 -0
- package/src/workspace/layout/GridNode.js +280 -0
- package/src/workspace/layout/LayoutNode.js +89 -0
- package/src/workspace/layout/PartNode.js +77 -0
- package/src/workspace/layout/SplitNode.js +114 -0
- package/src/workspace/layout/TabsNode.js +191 -0
- package/src/workspace/layout/index.js +24 -0
- package/src/workspace/parts/AdapterPart.js +33 -0
- package/src/workspace/parts/ArchimateCanvasPart.js +345 -0
- package/src/workspace/parts/ArchimateEditorPart.js +79 -0
- package/src/workspace/parts/ChartPart.js +115 -0
- package/src/workspace/parts/ContentPart.js +34 -0
- package/src/workspace/parts/DetailPart.js +46 -0
- package/src/workspace/parts/DiagramEditorPart.js +135 -0
- package/src/workspace/parts/EditorPart.js +388 -0
- package/src/workspace/parts/HtmlPart.js +25 -0
- package/src/workspace/parts/ListPart.js +57 -0
- package/src/workspace/parts/ModelFile.js +187 -0
- package/src/workspace/parts/ModelsPart.js +135 -0
- package/src/workspace/styles.js +258 -0
- package/src/workspace/themes.js +96 -0
- package/src/workspace/workArea.js +413 -0
- package/src/workspace/workAreaModel.js +197 -0
- package/src/workspace.js +16 -0
- package/src/zip/ZipArchive.js +160 -0
- package/src/zip/crc32.js +25 -0
- package/src/zip/inflate.js +159 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { ViewSetChecker } from '../diagramModel/ViewSetChecker.js';
|
|
2
|
+
import { ArchimateValidator } from './ArchimateValidator.js';
|
|
3
|
+
import { viewNestings, nestingRelationships } from './nesting.js';
|
|
4
|
+
import { duplicateGroups, UNPRINTABLE } from './duplicates.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ArchimateModelChecker — the checks Archi's validator makes over a model,
|
|
8
|
+
* on top of the view-set ones (empty views): relationships the specification
|
|
9
|
+
* does not allow, elements that look like the same thing twice, and elements
|
|
10
|
+
* and relationships no view shows (a relationship a nesting stands for counts
|
|
11
|
+
* as shown), and elements nested in another with no relationship for it.
|
|
12
|
+
* Findings name elements, relationships or views (`kind`).
|
|
13
|
+
*/
|
|
14
|
+
export class ArchimateModelChecker extends ViewSetChecker {
|
|
15
|
+
/**
|
|
16
|
+
* @param {ArchimateModel} model
|
|
17
|
+
* @param {Object} [options]
|
|
18
|
+
* @param {string} [options.version] - ArchiMate version for the relationship check ('3.2' | '4')
|
|
19
|
+
*/
|
|
20
|
+
constructor(model, { version = '4' } = {}) {
|
|
21
|
+
super(model);
|
|
22
|
+
this.version = version;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
checks() {
|
|
26
|
+
return [this.invalidRelationships, this.possibleDuplicates, this.unusedElements, this.unusedRelationships, this.nestedWithoutRelationship, this.unprintableText, ...super.checks()];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Elements drawn on no view. */
|
|
30
|
+
unusedElements() {
|
|
31
|
+
const drawn = new Set(this.model.views().flatMap(v => [...v.elementInstances.values()].map(i => i.elementId)));
|
|
32
|
+
return this.model.elements()
|
|
33
|
+
.filter(e => !drawn.has(e.id))
|
|
34
|
+
.map(e => ({ code: 'unused-element', severity: 'info', kind: 'element', ids: [e.id], message: `"${this._name(e)}" is in no view` }));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Relationships drawn on no view, nor shown by a nesting (an element drawn inside another). */
|
|
38
|
+
unusedRelationships() {
|
|
39
|
+
const drawn = new Set(this.model.views().flatMap(v => [...v.relationshipInstances.values()].map(i => i.relationshipId)));
|
|
40
|
+
for (const n of this.model.views().flatMap(v => viewNestings(v))) {
|
|
41
|
+
for (const r of nestingRelationships(this.model, n.parentElementId, n.childElementId)) drawn.add(r.id);
|
|
42
|
+
}
|
|
43
|
+
return this.model.relationships()
|
|
44
|
+
.filter(r => !drawn.has(r.id))
|
|
45
|
+
.map(r => ({ code: 'unused-relationship', severity: 'info', kind: 'relationship', ids: [r.id], message: `${this._relationshipText(r)} is in no view` }));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Elements drawn inside another on a view with no relationship from the
|
|
50
|
+
* parent to it that a nesting stands for (NESTING_KINDS): the drawing says
|
|
51
|
+
* more than the model does. One finding per view and pair.
|
|
52
|
+
*/
|
|
53
|
+
nestedWithoutRelationship() {
|
|
54
|
+
const seen = new Set();
|
|
55
|
+
return this.model.views().flatMap(v => viewNestings(v))
|
|
56
|
+
.filter(n => !nestingRelationships(this.model, n.parentElementId, n.childElementId).length)
|
|
57
|
+
.filter(n => { const key = `${n.view.id}\u0000${n.parentElementId}\u0000${n.childElementId}`; return !seen.has(key) && seen.add(key); })
|
|
58
|
+
.map(n => {
|
|
59
|
+
const [parent, child] = [n.parentElementId, n.childElementId].map(id => this.model.getElement(id));
|
|
60
|
+
return {
|
|
61
|
+
code: 'nested-without-relationship', severity: 'warning', kind: 'element', ids: [n.childElementId], viewId: n.view.id,
|
|
62
|
+
message: `"${this._name(child)}" is drawn inside "${this._name(parent)}" on "${n.view.name || n.view.id}" with no relationship between them`,
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Elements of the same type whose names have the same words (ignoring
|
|
69
|
+
* case, punctuation, word order and filler words: duplicates.js): likely
|
|
70
|
+
* one thing twice. The finding names them all, so they can be merged.
|
|
71
|
+
*/
|
|
72
|
+
possibleDuplicates() {
|
|
73
|
+
return duplicateGroups(this.model.elements()).map(g => {
|
|
74
|
+
// Names that differ only in case and spacing are one name to the reader.
|
|
75
|
+
const byLook = new Map();
|
|
76
|
+
for (const e of g) {
|
|
77
|
+
const look = this._name(e).trim().replace(/\s+/g, ' ').toLowerCase();
|
|
78
|
+
if (!byLook.has(look)) byLook.set(look, this._name(e).trim());
|
|
79
|
+
}
|
|
80
|
+
const names = [...byLook.values()];
|
|
81
|
+
return {
|
|
82
|
+
code: 'possible-duplicate', severity: 'warning', kind: 'element', ids: g.map(e => e.id),
|
|
83
|
+
message: names.length === 1
|
|
84
|
+
? `${g.length} ${g[0].type} elements are named "${names[0]}"`
|
|
85
|
+
: `${g.length} ${g[0].type} elements look the same: ${names.map(n => `"${n}"`).join(', ')}`,
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Names and documentation of elements and relationships with characters that should not be there (control characters, zero-width spaces). */
|
|
91
|
+
unprintableText() {
|
|
92
|
+
const found = [];
|
|
93
|
+
const look = (kind, item) => {
|
|
94
|
+
const fields = [['name', UNPRINTABLE.name], ['documentation', UNPRINTABLE.documentation]].filter(([f, re]) => re.test(String(item[f] ?? '')));
|
|
95
|
+
if (fields.length) {
|
|
96
|
+
found.push({
|
|
97
|
+
code: 'unprintable-text', severity: 'warning', kind, ids: [item.id],
|
|
98
|
+
message: `${kind === 'element' ? `"${this._name(item).replace(UNPRINTABLE.name, '?')}"` : this._relationshipText(item)} has unprintable characters in its ${fields.map(([f]) => f).join(' and ')}`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
this.model.elements().forEach(e => look('element', e));
|
|
103
|
+
this.model.relationships().forEach(r => look('relationship', r));
|
|
104
|
+
return found;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Relationships the ArchiMate specification does not allow between their ends. */
|
|
108
|
+
invalidRelationships() {
|
|
109
|
+
const warnings = ArchimateValidator.validateModel(this.model.elements(), this.model.relationships(), this.version);
|
|
110
|
+
return warnings
|
|
111
|
+
.filter(w => w.type === 'relationship' && w.relationship)
|
|
112
|
+
.map(w => ({ code: w.code ?? 'invalid-relationship', severity: 'warning', kind: 'relationship', ids: [w.relationship.id], message: `${this._relationshipText(w.relationship)}: ${w.message}` }));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** @private */
|
|
116
|
+
_name(element) {
|
|
117
|
+
return element?.name || element?.id || '?';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** @private */
|
|
121
|
+
_relationshipText(r) {
|
|
122
|
+
const end = (id) => { const e = this.model.getElement(id); return e ? this._name(e) : id; };
|
|
123
|
+
return `${r.kind || 'association'} from "${end(r.source)}" to "${end(r.target)}"`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { ModelReport } from '../diagramModel/ModelReport.js';
|
|
2
|
+
import { ArchimateDiagram } from './ArchimateDiagram.js';
|
|
3
|
+
import { TREE_LAYERS, treeLayerOf } from '../modelTree/treeLayers.js';
|
|
4
|
+
import { typeTitle } from '../archimate/archimateNames.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ArchimateModelReport — the report of an ArchiMate model (as Archi's HTML
|
|
8
|
+
* report): on top of the views, a page per element (its type and layer
|
|
9
|
+
* colour, documentation, properties, its relationships with the element at
|
|
10
|
+
* the other end, the views it is on) and per relationship (its source and
|
|
11
|
+
* target, the views it is on); a view's page lists its elements and
|
|
12
|
+
* relationships. The tree has Elements by layer, as the model tree has them,
|
|
13
|
+
* and Relationships by kind.
|
|
14
|
+
*/
|
|
15
|
+
export class ArchimateModelReport extends ModelReport {
|
|
16
|
+
modelFacts() {
|
|
17
|
+
return [
|
|
18
|
+
{ label: 'Elements', text: String(this.model.elements().length) },
|
|
19
|
+
{ label: 'Relationships', text: String(this.model.relationships().length) },
|
|
20
|
+
...super.modelFacts(),
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
viewType(view) {
|
|
25
|
+
return view.constructor.kind === 'canvas' ? 'Canvas' : 'View';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
viewFacts(view) {
|
|
29
|
+
return view.viewpoint ? [{ label: 'Viewpoint', text: typeTitle(String(view.viewpoint)) }] : [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** A view's elements and relationships, each once, in the order they were placed. */
|
|
33
|
+
viewLists(view) {
|
|
34
|
+
const once = (ids) => [...new Set(ids)];
|
|
35
|
+
const elementIds = once([...(view.elementInstances?.values() ?? [])].map(i => i.elementId))
|
|
36
|
+
.filter(id => id && this.model.getElement(id));
|
|
37
|
+
const relationshipIds = once([...(view.relationshipInstances?.values() ?? [])].map(i => i.relationshipId))
|
|
38
|
+
.filter(id => id && this.model.getRelationship(id));
|
|
39
|
+
return [
|
|
40
|
+
{ title: 'Elements', rows: elementIds.map(id => ({ key: this.key('element', id), note: typeTitle(this.model.getElement(id).type ?? '') })) },
|
|
41
|
+
// A named relationship's row says which elements it joins; an unnamed one's name already does.
|
|
42
|
+
{ title: 'Relationships', rows: relationshipIds.map(id => { const rel = this.model.getRelationship(id); return { key: this.key('relationship', id), ...(rel.name && { note: this.ends(rel) }) }; }) },
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
conceptItems() {
|
|
47
|
+
return [...this.model.elements().map(e => this.elementItem(e)), ...this.model.relationships().map(r => this.relationshipItem(r))];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** An element's page. */
|
|
51
|
+
elementItem(element) {
|
|
52
|
+
const { incoming, outgoing } = this.model.relationshipsFor(element.id);
|
|
53
|
+
// An unnamed relationship's name already says which elements it joins; a named one's row says the other end.
|
|
54
|
+
const row = (rel, other, arrow) => ({ key: this.key('relationship', rel.id), ...(rel.name && { note: `${arrow} ${this.nameOf(other)}` }) });
|
|
55
|
+
return this.item('element', element.id, {
|
|
56
|
+
name: element.name,
|
|
57
|
+
type: typeTitle(element.type ?? 'element'),
|
|
58
|
+
color: this.colorOf(element),
|
|
59
|
+
documentation: element.documentation,
|
|
60
|
+
properties: element.properties,
|
|
61
|
+
facts: [{ label: 'Layer', text: typeTitle(treeLayerOf(element)) }],
|
|
62
|
+
lists: [
|
|
63
|
+
{ title: 'Relationships', rows: [...outgoing.map(r => row(r, r.target, '→')), ...incoming.map(r => row(r, r.source, '←'))] },
|
|
64
|
+
{ title: 'Views', rows: this.model.views().filter(v => v.elementInstancesFor?.(element.id).length).map(v => ({ key: this.key('view', v.id) })) },
|
|
65
|
+
],
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** A relationship's page. */
|
|
70
|
+
relationshipItem(rel) {
|
|
71
|
+
const end = (label, id) => (this.model.getElement(id) ? { label, key: this.key('element', id) } : { label, text: String(id ?? '') });
|
|
72
|
+
return this.item('relationship', rel.id, {
|
|
73
|
+
name: this.relationshipName(rel),
|
|
74
|
+
type: `${typeTitle(this.kindOf(rel))} relationship`,
|
|
75
|
+
documentation: rel.documentation,
|
|
76
|
+
properties: rel.properties,
|
|
77
|
+
facts: [end('Source', rel.source), end('Target', rel.target)],
|
|
78
|
+
lists: [{ title: 'Views', rows: this.model.views().filter(v => v.relationshipInstancesFor?.(rel.id).length).map(v => ({ key: this.key('view', v.id) })) }],
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** A relationship's name, or (most have none) its kind and ends. */
|
|
83
|
+
relationshipName(rel) {
|
|
84
|
+
return rel.name || `${typeTitle(this.kindOf(rel))}: ${this.ends(rel)}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Elements by layer (in the model tree's order), then relationships by kind. */
|
|
88
|
+
conceptSections() {
|
|
89
|
+
const elements = this.model.elements();
|
|
90
|
+
const relationships = this.model.relationships();
|
|
91
|
+
const byLayer = TREE_LAYERS.map(layer => ({
|
|
92
|
+
title: typeTitle(layer),
|
|
93
|
+
keys: this.sorted(elements.filter(e => treeLayerOf(e) === layer)).map(e => this.key('element', e.id)),
|
|
94
|
+
}));
|
|
95
|
+
const kinds = [...new Set(relationships.map(r => this.kindOf(r)))].sort();
|
|
96
|
+
const byKind = kinds.map(kind => ({
|
|
97
|
+
title: typeTitle(kind),
|
|
98
|
+
keys: this.sorted(relationships.filter(r => this.kindOf(r) === kind), r => this.relationshipName(r))
|
|
99
|
+
.map(r => this.key('relationship', r.id)),
|
|
100
|
+
}));
|
|
101
|
+
return [{ title: 'Elements', groups: byLayer }, { title: 'Relationships', groups: byKind }];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** A relationship's kind ('serving', ...): `kind`, or `type` as some sources write it. */
|
|
105
|
+
kindOf(rel) {
|
|
106
|
+
return rel.kind ?? rel.type ?? 'relationship';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** "Source → Target" by name. */
|
|
110
|
+
ends(rel) {
|
|
111
|
+
return `${this.nameOf(rel.source)} → ${this.nameOf(rel.target)}`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** @private */
|
|
115
|
+
nameOf(elementId) {
|
|
116
|
+
return this.model.getElement(elementId)?.name || elementId || '?';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** @private */
|
|
120
|
+
colorOf(element) {
|
|
121
|
+
return element.fillColor || ArchimateDiagram.layerColor(ArchimateDiagram.elementLayer(element));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** @private */
|
|
125
|
+
sorted(items, name = (i) => i.name ?? '') {
|
|
126
|
+
return [...items].sort((a, b) => String(name(a)).localeCompare(String(name(b))));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ModelSearch } from '../diagramModel/ModelSearch.js';
|
|
2
|
+
import { ViewObjectInstance } from './ViewObjectInstance.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ArchimateModelSearch — find and replace in an ArchiMate model (as Archi's
|
|
6
|
+
* Find/Replace): on top of the model and views (ModelSearch), every element's
|
|
7
|
+
* and relationship's name, documentation and properties, and the text of the
|
|
8
|
+
* notes on each view.
|
|
9
|
+
*/
|
|
10
|
+
export class ArchimateModelSearch extends ModelSearch {
|
|
11
|
+
conceptTargets() {
|
|
12
|
+
const concept = (kind, c) => {
|
|
13
|
+
const owner = { kind, id: c.id, owner: c.name || c.id };
|
|
14
|
+
return [this.text(owner, 'name', c), this.text(owner, 'documentation', c), ...this.propertyTargets(owner, c.properties)];
|
|
15
|
+
};
|
|
16
|
+
return [
|
|
17
|
+
...this.model.elements().flatMap(e => concept('element', e)),
|
|
18
|
+
...this.model.relationships().flatMap(r => concept('relationship', r)),
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Elements and relationships hold properties too. */
|
|
23
|
+
propertyHolders() {
|
|
24
|
+
return [
|
|
25
|
+
...super.propertyHolders(),
|
|
26
|
+
...this.model.elements().map(e => ({ owner: `element ${e.id}`, object: e })),
|
|
27
|
+
...this.model.relationships().map(r => ({ owner: `relationship ${r.id}`, object: r })),
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** A note's text (its `label`, and the `name` it is listed by), which belongs to its view. */
|
|
32
|
+
viewItemTargets(view) {
|
|
33
|
+
return [...(view.elementInstances?.values() ?? [])]
|
|
34
|
+
.filter(inst => inst instanceof ViewObjectInstance && inst.content.shape === 'note')
|
|
35
|
+
.map(inst => ({
|
|
36
|
+
kind: 'note', id: inst.id, viewId: view.id, owner: 'Note', field: 'name', fieldLabel: 'Text',
|
|
37
|
+
read: () => inst.content.label ?? '',
|
|
38
|
+
write: (text) => { inst.content.label = text; inst.content.name = text; },
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { ArchimateNotation, ArchimateViewpoints, archimate32Type } from '../../archimate.js';
|
|
2
|
+
import { ITIconNotation } from '../../itIcons.js';
|
|
3
|
+
import { RELATIONSHIP_LETTERS, RELATIONSHIP_TABLE_CONCEPTS, RELATIONSHIP_TABLE_ROWS, RELATIONSHIP_TABLE_VERSION } from '../../archimateRelationshipTable.js';
|
|
4
|
+
|
|
5
|
+
/** source type -> target type -> Set of allowed kinds, from the specification's table (built on first use). */
|
|
6
|
+
let SPEC_TABLE = null;
|
|
7
|
+
function specTable() {
|
|
8
|
+
if (SPEC_TABLE) return SPEC_TABLE;
|
|
9
|
+
SPEC_TABLE = new Map();
|
|
10
|
+
for (const [source, row] of Object.entries(RELATIONSHIP_TABLE_ROWS)) {
|
|
11
|
+
const targets = new Map();
|
|
12
|
+
row.split(',').forEach((letters, i) => {
|
|
13
|
+
targets.set(RELATIONSHIP_TABLE_CONCEPTS[i], new Set([...letters].map(c => RELATIONSHIP_LETTERS[c]).filter(Boolean)));
|
|
14
|
+
});
|
|
15
|
+
SPEC_TABLE.set(source, targets);
|
|
16
|
+
}
|
|
17
|
+
return SPEC_TABLE;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* ArchimateValidator — DOM-free ArchiMate standard-alignment checks.
|
|
22
|
+
*
|
|
23
|
+
* The validator is advisory: it returns warnings, it never blocks rendering.
|
|
24
|
+
* Rules are encoded as data so they can be tuned as the standard interpretation
|
|
25
|
+
* evolves. Custom/unofficial element types are allowed through without warnings
|
|
26
|
+
* unless the relationship kind is clearly nonsensical for the resolved aspects.
|
|
27
|
+
*
|
|
28
|
+
* Coverage:
|
|
29
|
+
* - Relationship validity by source/target aspect and layer.
|
|
30
|
+
* - v4 Common Domain elements (process/function/service/interaction/event)
|
|
31
|
+
* must carry an explicit `layer` field (their type no longer implies one).
|
|
32
|
+
* - v3.2 types used under v4 are flagged as migrated/retired.
|
|
33
|
+
*/
|
|
34
|
+
export class ArchimateValidator {
|
|
35
|
+
/** The 11 official relationship kinds (plus the directed-association alias). */
|
|
36
|
+
static RELATIONSHIP_KINDS = [
|
|
37
|
+
'composition', 'aggregation', 'assignment', 'realization',
|
|
38
|
+
'specialization', 'access', 'serving', 'influence', 'triggering', 'flow',
|
|
39
|
+
'association', 'association-directed',
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Allow-rule matrix, for element types the specification's table does not
|
|
44
|
+
* cover (custom and IT types; see specificationKinds). Each rule describes
|
|
45
|
+
* when a given set of relationship kinds is valid between a source and target. The first matching rule wins;
|
|
46
|
+
* if no rule matches, the relationship is flagged as a warning.
|
|
47
|
+
* Association is the final, permissive fallback. A rule may also name the
|
|
48
|
+
* element types it applies to (`fromTypes`, `toTypes`) when the standard
|
|
49
|
+
* allows a pairing for those types only.
|
|
50
|
+
*/
|
|
51
|
+
static RULES = [
|
|
52
|
+
// Structural: whole-part, same-aspect, same-layer preferred.
|
|
53
|
+
{
|
|
54
|
+
kinds: ['composition', 'aggregation'],
|
|
55
|
+
sameAspect: true,
|
|
56
|
+
sameLayer: true,
|
|
57
|
+
message: 'Composition and aggregation are normally used between elements of the same aspect and layer',
|
|
58
|
+
},
|
|
59
|
+
// Assignment between named active-structure types: "a business actor may
|
|
60
|
+
// be assigned to one or more business roles" (ArchiMate 3.2, 8.2.1; also 4).
|
|
61
|
+
{
|
|
62
|
+
kinds: ['assignment'],
|
|
63
|
+
fromTypes: ['business-actor'],
|
|
64
|
+
toTypes: ['business-role'],
|
|
65
|
+
message: 'A business actor is assigned to the business roles it fulfils',
|
|
66
|
+
},
|
|
67
|
+
// Assignment: active structure performs/responsible for behavior or passive structure.
|
|
68
|
+
{
|
|
69
|
+
kinds: ['assignment'],
|
|
70
|
+
fromAspect: 'active-structure',
|
|
71
|
+
toAspects: ['behavior', 'passive-structure'],
|
|
72
|
+
message: 'Assignment usually goes from an active-structure element to a behavior or passive-structure element',
|
|
73
|
+
},
|
|
74
|
+
// Realization: behavior (or active structure) realizes a passive structure.
|
|
75
|
+
{
|
|
76
|
+
kinds: ['realization'],
|
|
77
|
+
fromAspects: ['behavior', 'active-structure'],
|
|
78
|
+
toAspect: 'passive-structure',
|
|
79
|
+
message: 'Realization usually goes from a behavior or active-structure element to a passive-structure element',
|
|
80
|
+
},
|
|
81
|
+
// Specialization: same aspect/layer.
|
|
82
|
+
{
|
|
83
|
+
kinds: ['specialization'],
|
|
84
|
+
sameAspect: true,
|
|
85
|
+
sameLayer: true,
|
|
86
|
+
message: 'Specialization is normally between elements of the same aspect and layer',
|
|
87
|
+
},
|
|
88
|
+
// Access: behavior reads/writes passive structure.
|
|
89
|
+
{
|
|
90
|
+
kinds: ['access'],
|
|
91
|
+
fromAspect: 'behavior',
|
|
92
|
+
toAspect: 'passive-structure',
|
|
93
|
+
message: 'Access usually goes from a behavior element to a passive-structure element',
|
|
94
|
+
},
|
|
95
|
+
// Serving: behavior serves behavior, may cross layers.
|
|
96
|
+
{
|
|
97
|
+
kinds: ['serving'],
|
|
98
|
+
fromAspect: 'behavior',
|
|
99
|
+
toAspect: 'behavior',
|
|
100
|
+
crossLayer: true,
|
|
101
|
+
message: 'Serving usually goes from one behavior element to another',
|
|
102
|
+
},
|
|
103
|
+
// Triggering: behavior triggers behavior.
|
|
104
|
+
{
|
|
105
|
+
kinds: ['triggering'],
|
|
106
|
+
fromAspects: ['behavior', 'motivation'],
|
|
107
|
+
toAspects: ['behavior', 'motivation'],
|
|
108
|
+
message: 'Triggering usually goes from one behavior or event element to another',
|
|
109
|
+
},
|
|
110
|
+
// Flow: behavior to behavior or passive structure to passive structure.
|
|
111
|
+
{
|
|
112
|
+
kinds: ['flow'],
|
|
113
|
+
sameAspect: true,
|
|
114
|
+
aspects: ['behavior', 'passive-structure'],
|
|
115
|
+
message: 'Flow is normally between behavior elements, or between passive-structure elements',
|
|
116
|
+
},
|
|
117
|
+
// Influence: very broad, but motivation elements are the natural source.
|
|
118
|
+
{
|
|
119
|
+
kinds: ['influence'],
|
|
120
|
+
message: 'Influence is broadly allowed; ensure the direction matches your intent',
|
|
121
|
+
severity: 'info',
|
|
122
|
+
},
|
|
123
|
+
// Association: permissive fallback.
|
|
124
|
+
{
|
|
125
|
+
kinds: ['association', 'association-directed'],
|
|
126
|
+
message: 'Association is the permissive fallback relationship',
|
|
127
|
+
severity: 'info',
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Validate a single relationship.
|
|
133
|
+
* @param {object} sourceElement
|
|
134
|
+
* @param {object} targetElement
|
|
135
|
+
* @param {string} kind
|
|
136
|
+
* @param {'3.2'|'4'} [version='4']
|
|
137
|
+
* @returns {{valid: boolean, code?: string, message?: string, severity?: string, suggestedKinds?: string[]}}
|
|
138
|
+
*/
|
|
139
|
+
static validateRelationship(sourceElement, targetElement, kind, version = '4') {
|
|
140
|
+
const source = this._resolve(sourceElement, version);
|
|
141
|
+
const target = this._resolve(targetElement, version);
|
|
142
|
+
const normalizedKind = kind || 'association';
|
|
143
|
+
|
|
144
|
+
// Unknown kind is itself a warning (fall back to association notation).
|
|
145
|
+
if (!this.RELATIONSHIP_KINDS.includes(normalizedKind)) {
|
|
146
|
+
return {
|
|
147
|
+
valid: false,
|
|
148
|
+
code: 'unknown-kind',
|
|
149
|
+
message: `Unknown relationship kind "${normalizedKind}"; falling back to association`,
|
|
150
|
+
severity: 'warning',
|
|
151
|
+
suggestedKinds: ['association'],
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Custom/unofficial types on both ends are allowed any relationship so
|
|
156
|
+
// validation stays helpful without punishing informal extensions.
|
|
157
|
+
if (source.isCustom && target.isCustom) {
|
|
158
|
+
return { valid: true };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Two ArchiMate types: the specification's own table decides.
|
|
162
|
+
const allowed = this.specificationKinds(sourceElement, targetElement);
|
|
163
|
+
if (allowed) {
|
|
164
|
+
if (allowed.has(normalizedKind)) return { valid: true };
|
|
165
|
+
const suggested = this.RELATIONSHIP_KINDS.filter(k => allowed.has(k));
|
|
166
|
+
return {
|
|
167
|
+
valid: false,
|
|
168
|
+
code: 'not-in-specification',
|
|
169
|
+
message: `ArchiMate ${RELATIONSHIP_TABLE_VERSION} does not allow ${normalizedKind} from ${archimate32Type(sourceElement)} to ${archimate32Type(targetElement)}`,
|
|
170
|
+
severity: 'warning',
|
|
171
|
+
suggestedKinds: suggested.length ? suggested : ['association'],
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const rule = this._matchingRule(normalizedKind, source, target);
|
|
176
|
+
if (rule) {
|
|
177
|
+
return { valid: true };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const suggested = this.allowedKinds(sourceElement, targetElement, version)
|
|
181
|
+
.filter(k => k !== normalizedKind);
|
|
182
|
+
return {
|
|
183
|
+
valid: false,
|
|
184
|
+
code: 'aspect-or-layer-mismatch',
|
|
185
|
+
message: `Relationship "${normalizedKind}" is unusual between a ${source.aspect} element and a ${target.aspect} element`,
|
|
186
|
+
severity: 'warning',
|
|
187
|
+
suggestedKinds: suggested.length ? suggested : ['association'],
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Validate an entire model.
|
|
193
|
+
* @param {Array<object>} elements
|
|
194
|
+
* @param {Array<object>} relationships
|
|
195
|
+
* @param {'3.2'|'4'} [version='4']
|
|
196
|
+
* @returns {Array<object>} warnings, each with {type, code, message, severity, element?, relationship?, source?, target?}
|
|
197
|
+
*/
|
|
198
|
+
static validateModel(elements, relationships, version = '4', viewpoint = null, customViewpoints = []) {
|
|
199
|
+
const warnings = [];
|
|
200
|
+
const byId = new Map((elements || []).map(e => [e.id, e]));
|
|
201
|
+
|
|
202
|
+
for (const element of elements || []) {
|
|
203
|
+
// Diagram annotations are not ArchiMate model elements; skip them.
|
|
204
|
+
if (element?.shape === 'note' || element?.annotation === true) continue;
|
|
205
|
+
const elementWarnings = this._validateElement(element, version);
|
|
206
|
+
for (const w of elementWarnings) {
|
|
207
|
+
warnings.push({ ...w, type: 'element', element });
|
|
208
|
+
}
|
|
209
|
+
if (viewpoint && viewpoint !== 'All') {
|
|
210
|
+
const vpWarning = ArchimateViewpoints.validateElement(element, viewpoint, version, customViewpoints);
|
|
211
|
+
if (vpWarning) {
|
|
212
|
+
warnings.push({ type: 'element', code: 'viewpoint-mismatch', severity: 'warning', message: vpWarning, element });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
for (const relationship of relationships || []) {
|
|
218
|
+
const source = byId.get(relationship.source);
|
|
219
|
+
const target = byId.get(relationship.target);
|
|
220
|
+
if (!source) {
|
|
221
|
+
warnings.push({ type: 'relationship', code: 'missing-source', relationship, severity: 'warning', message: `Relationship references missing source "${relationship.source}"` });
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (!target) {
|
|
225
|
+
warnings.push({ type: 'relationship', code: 'missing-target', relationship, severity: 'warning', message: `Relationship references missing target "${relationship.target}"` });
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
const result = this.validateRelationship(source, target, relationship.kind, version);
|
|
229
|
+
if (!result.valid) {
|
|
230
|
+
warnings.push({
|
|
231
|
+
type: 'relationship',
|
|
232
|
+
code: result.code,
|
|
233
|
+
severity: result.severity,
|
|
234
|
+
message: result.message,
|
|
235
|
+
suggestedKinds: result.suggestedKinds,
|
|
236
|
+
relationship,
|
|
237
|
+
source,
|
|
238
|
+
target,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return warnings;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Return the relationship kinds permitted between two elements.
|
|
248
|
+
* @param {object} sourceElement
|
|
249
|
+
* @param {object} targetElement
|
|
250
|
+
* @param {'3.2'|'4'} [version='4']
|
|
251
|
+
* @returns {string[]}
|
|
252
|
+
*/
|
|
253
|
+
static allowedKinds(sourceElement, targetElement, version = '4') {
|
|
254
|
+
const source = this._resolve(sourceElement, version);
|
|
255
|
+
const target = this._resolve(targetElement, version);
|
|
256
|
+
if (source.isCustom && target.isCustom) {
|
|
257
|
+
return [...this.RELATIONSHIP_KINDS];
|
|
258
|
+
}
|
|
259
|
+
const allowed = this.specificationKinds(sourceElement, targetElement);
|
|
260
|
+
if (allowed) return this.RELATIONSHIP_KINDS.filter(kind => allowed.has(kind));
|
|
261
|
+
return this.RELATIONSHIP_KINDS.filter(kind => this._matchingRule(kind, source, target));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* The relationship kinds the ArchiMate specification's relationship table
|
|
266
|
+
* (Appendix B) allows from one element to another, or null when either is
|
|
267
|
+
* not an ArchiMate type (a custom or IT type: RULES apply instead). An
|
|
268
|
+
* ArchiMate 4 type is looked up as its 3.2 type (archimate32Type). A
|
|
269
|
+
* directed association is an association.
|
|
270
|
+
* @param {object} sourceElement
|
|
271
|
+
* @param {object} targetElement
|
|
272
|
+
* @returns {Set<string>|null}
|
|
273
|
+
*/
|
|
274
|
+
static specificationKinds(sourceElement, targetElement) {
|
|
275
|
+
const row = specTable().get(archimate32Type(sourceElement ?? {}));
|
|
276
|
+
const kinds = row?.get(archimate32Type(targetElement ?? {}));
|
|
277
|
+
if (!kinds) return null;
|
|
278
|
+
return kinds.has('association') ? new Set([...kinds, 'association-directed']) : kinds;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
static _resolve(element, version) {
|
|
282
|
+
const typeName = element?.type;
|
|
283
|
+
// A 3.2 type retired in 4 keeps its 3.2 layer and aspect, so its relationships
|
|
284
|
+
// are still checked; _validateElement flags the retirement itself.
|
|
285
|
+
const type = typeof typeName === 'string'
|
|
286
|
+
? (ArchimateNotation.elementType(typeName, version)
|
|
287
|
+
|| ArchimateNotation.elementType(typeName, '3.2')
|
|
288
|
+
|| ITIconNotation.elementType(typeName))
|
|
289
|
+
: undefined;
|
|
290
|
+
const layerName = element?.layer
|
|
291
|
+
? element.layer
|
|
292
|
+
: (type?.layer?.name || ArchimateNotation.elementLayer(element, version));
|
|
293
|
+
const aspect = type?.aspect || element?.aspect || 'other';
|
|
294
|
+
return {
|
|
295
|
+
type: typeName,
|
|
296
|
+
resolvedType: type,
|
|
297
|
+
layer: layerName,
|
|
298
|
+
aspect,
|
|
299
|
+
isCustom: !type,
|
|
300
|
+
isCommonDomain: type && type.layer === null && !element?.layer,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
static _validateElement(element, version) {
|
|
305
|
+
const warnings = [];
|
|
306
|
+
const type = typeof element?.type === 'string' ? ArchimateNotation.elementType(element.type, version) : undefined;
|
|
307
|
+
|
|
308
|
+
if (!type && element?.type && !ArchimateNotation.elementType(element.type, '3.2')) {
|
|
309
|
+
// Custom types are allowed; no warning. (A 3.2 type under 4 is retired, not custom.)
|
|
310
|
+
return warnings;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (version === '4' && type?.layer === null && !element?.layer) {
|
|
314
|
+
warnings.push({
|
|
315
|
+
code: 'common-domain-missing-layer',
|
|
316
|
+
severity: 'warning',
|
|
317
|
+
message: `Element "${element.name || element.id}" is a Common Domain type (${element.type}) and needs an explicit layer in ArchiMate 4`,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (version === '4' && ArchimateNotation.elementType(element?.type, '3.2') && !ArchimateNotation.elementType(element?.type, '4')) {
|
|
322
|
+
warnings.push({
|
|
323
|
+
code: 'retired-type-in-v4',
|
|
324
|
+
severity: 'warning',
|
|
325
|
+
message: `Element type "${element.type}" is retired in ArchiMate 4; use migrateElementToV4() or switch to archimateVersion:"3.2"`,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return warnings;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
static _matchingRule(kind, source, target) {
|
|
333
|
+
for (const rule of this.RULES) {
|
|
334
|
+
if (!rule.kinds.includes(kind)) continue;
|
|
335
|
+
|
|
336
|
+
const sourceAspects = rule.fromAspects || (rule.fromAspect ? [rule.fromAspect] : undefined);
|
|
337
|
+
const targetAspects = rule.toAspects || (rule.toAspect ? [rule.toAspect] : undefined);
|
|
338
|
+
const allAspects = rule.aspects;
|
|
339
|
+
|
|
340
|
+
if (rule.fromTypes && !rule.fromTypes.includes(source.type)) continue;
|
|
341
|
+
if (rule.toTypes && !rule.toTypes.includes(target.type)) continue;
|
|
342
|
+
if (sourceAspects && !sourceAspects.includes(source.aspect)) continue;
|
|
343
|
+
if (targetAspects && !targetAspects.includes(target.aspect)) continue;
|
|
344
|
+
if (allAspects && (!allAspects.includes(source.aspect) || !allAspects.includes(target.aspect))) continue;
|
|
345
|
+
|
|
346
|
+
if (rule.sameAspect && source.aspect !== target.aspect) continue;
|
|
347
|
+
if (rule.sameLayer && source.layer !== target.layer) continue;
|
|
348
|
+
if (rule.crossLayer === false && source.layer !== target.layer) continue;
|
|
349
|
+
|
|
350
|
+
if (rule.fromLayer && rule.fromLayer !== source.layer) continue;
|
|
351
|
+
if (rule.toLayer && rule.toLayer !== target.layer) continue;
|
|
352
|
+
|
|
353
|
+
return rule;
|
|
354
|
+
}
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
}
|