Skip to content

Commit

Permalink
feat: Rework template indexing
Browse files Browse the repository at this point in the history
  • Loading branch information
vik378 committed Jun 28, 2024
1 parent ef78dfa commit 30e4b83
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 35 deletions.
80 changes: 80 additions & 0 deletions capella_model_explorer/backend/templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from pydantic import BaseModel, Field
from pathlib import Path
from typing import List, Dict, Optional
import yaml
import capellambse


class TemplateScope(BaseModel):
type: str = Field(..., title="Model Element Type")
below: Optional[str] = Field(None, title="Model element to search below, scope limiter")

class Template(BaseModel):
idx: str = Field(..., title="Template Identifier")
name: str = Field(..., title="Template Name")
template: Path = Field(..., title="Template File Path")
description: str = Field(..., title="Template Description")
scope: TemplateScope = Field(..., title="Template Scope")

@property
def instances(self):
# eval the scope and return object list
pass


class TemplateCategory(BaseModel):
idx: str = Field(..., title="Category Identifier")
templates: List[Template] = Field([], title="Templates in this category")

def __getitem__(self, template_id: str):
return self.by_id(template_id)

def __add__(self, other):
if not isinstance(other, TemplateCategory):
return NotImplemented
return TemplateCategory(templates=self.templates + other.templates)



class TemplateCategories(BaseModel):
categories: List[TemplateCategory] = Field([], title="Template Categories")

def __getitem__(self, category_id: str):
return [cat for cat in self.categories if cat.idx == category_id].first()

def __add__(self, other):
if not isinstance(other, TemplateCategories):
return NotImplemented
for category in other.categories:
category_id = category.idx
if category_id in [cat.idx for cat in self.categories]:
self.categories[category_id].templates += category.templates
else:
self.categories.append(TemplateCategory(idx=category_id, templates=category.templates))
return self

def __len__(self):
return len(self.categories)

@property
def flat(self):
return {
template.idx: template
for category in self.categories
for template in category.templates
}

class TemplateLoader():
def __init__(self, model: capellambse.MelodyModel) -> None:
self.model = model
self.templates = TemplateCategories()

def index_path(self, path: Path) -> TemplateCategories:
self.templates = TemplateCategories() # reset templates
for template_file in path.glob("**/*.yaml"):
with template_file.open() as f:
templates_data = yaml.safe_load(template_file.read_text(encoding="utf8"))
if "categories" in templates_data:
self.templates += TemplateCategories(**templates_data)
return self.templates

28 changes: 0 additions & 28 deletions frontend/src/stories/TemplateCard.docs.mdx

This file was deleted.

10 changes: 5 additions & 5 deletions templates/system-analysis/system-actor.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
SPDX-License-Identifier: Apache-2.0
#}

{% from 'common_macros.html.j2' import show_other_attributes, description, render_reqs_by_type, typed_name, linked_name %}
{% from 'common_macros.html.j2' import show_other_attributes, description, render_reqs_by_type, typed_name, linked_name, linked_name_with_icon %}

{% if object.name %}
<h1>
Expand All @@ -27,21 +27,21 @@
{% if involving_caps %}
<p><b>{{ object.name }}</b> is involved in the following system capabilities:&nbsp;
{%- for cap in involving_caps -%}
{{ linked_name(cap) | safe }}{% if not loop.last %}, {% endif %}
{{ linked_name_with_icon(cap) | safe }}{% if not loop.last %}, {% endif %}
{%- endfor -%}
</p>
{% endif %}

<h2>Context</h2>
<p>The context of {{ object.name }} is summarized by the diagram below:</p>
{{ object.context_diagram.as_svg | safe }}
{{ object.context_diagram.render("svg", display_derived_interfaces=True) | safe }}

<h2>Functions</h2>
{% if object.allocated_functions %}
<p>The {{ object.name }} is responsible for the following functions:</p>
<ul>
{%- for func in object.allocated_functions -%}
<li>{{ linked_name(func) | safe }}</li>
<li>{{ linked_name_with_icon(func) | safe }}</li>
{%- endfor -%}
</ul>
{% else %}
Expand All @@ -54,7 +54,7 @@
<ul>
{%- for ex in object.related_exchanges -%}
{%- set partner = ex.source.owner if ex.source.owner != object else ex.target.owner -%}
<li>{{ linked_name(ex) | safe }} with {{ linked_name(partner) | safe }}</li>
<li>{{ linked_name_with_icon(ex) | safe }} with {{ linked_name_with_icon(partner) | safe }}</li>
{%- endfor -%}
</ul>
{% else %}
Expand Down
34 changes: 32 additions & 2 deletions tests/test_capella_model_explorer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,37 @@
# Copyright DB InfraGO AG and contributors
# SPDX-License-Identifier: Apache-2.0

import capella_model_explorer
import capellambse
from pathlib import Path
from capella_model_explorer.backend.templates import TemplateLoader, Template, TemplateCategory


def test_add_some_tests_here(): ...
def test_template_loading():
template_raw = {
"idx": "test",
"name": "Test Template",
"template": "test_template.jinja",
"description": "This is a test template",
"scope": {"type": "System", "below": "System"},
}
template = Template(**template_raw)

def test_category_loading():
template_raw = {
"idx": "test",
"name": "Test Template",
"template": "test_template.jinja",
"description": "This is a test template",
"scope": {"type": "System", "below": "System"},
}
category_raw = {
"idx": "test",
"templates": [template_raw],
}
category = TemplateCategory(**category_raw)

def test_index_templates():
model = capellambse.loadcli("coffee-machine")
templates = TemplateLoader(model).index_path(Path("."))
assert len(templates.flat) == 3
assert len(templates) == 1
27 changes: 27 additions & 0 deletions tests/test_index.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright DB InfraGO AG and contributors
# SPDX-License-Identifier: Apache-2.0

categories:
- idx: oa
templates:
- idx: operational-activity
name: Operational Activity
description: Specifies an operational activity.
template: operational-analysis/operational-activity.html.j2
scope:
type: OperationalActivity
below: oa
- idx: operational-capability
name: Operational Capability
description: Specifies an operational capability.
template: operational-analysis/operational-capability.html.j2
scope:
type: OperationalCapability
below: oa
- idx: operational-entity
name: Operational Entity
description: Specifies an operational entity.
template: operational-analysis/operational-entity.html.j2
scope:
type: Entity
below: oa

0 comments on commit 30e4b83

Please sign in to comment.