Skip to content

Commit faf723c

Browse files
authored
Merge pull request #7 from n7space/feature-mbep#333-image-support
Feature MBEP#333 image support
2 parents 094263a + 8874845 commit faf723c

33 files changed

Lines changed: 1268 additions & 42 deletions

README.md

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,52 @@ TP is a template processing engine developed for TASTE Document Generator. Its m
88

99
## Installation
1010

11-
TODO
11+
This project uses Python. The recommended way to install dependencies is via the provided Makefile which exposes a convenient `make install` target.
12+
13+
Prerequisites:
14+
- Python 3.10+ (or a compatible system Python)
1215

1316
## Configuration
1417

1518
None
1619

1720
## Running
1821

19-
The assumed use case is for the Template Processor to be invoked by TASTE Document Generator. However, if TP is to be used manually, the following command line interface, as documented in the built-in help, is available:
22+
The Template Processor can be run from the command line. The application name is `template-processor` which exposes the following arguments. Run the built-in help to see the same list:
23+
24+
```bash
25+
template-processor --help
26+
```
27+
28+
Key command-line arguments:
29+
30+
- `-i, --iv` : Input Interface View file (XML)
31+
- `-d, --dv` : Input Deployment View file (XML)
32+
- `-s, --system-objects` : One or more CSV files describing System Object Types (can be supplied multiple times)
33+
- `-v, --value` : One or more name=value pairs to provide template values (e.g., `-v TARGET=ASW`)
34+
- `-t, --template` : One or more template files to process (Mako templates). This argument can be provided multiple times.
35+
- `-m, --module-directory` : Module directory for Mako to use for compiled template modules (optional)
36+
- `-o, --output` : Output directory for processed templates (required)
37+
- `--verbosity` : Logging verbosity (choices `info`, `debug`, `warning`, `error`, default `warning`)
38+
- `-p, --postprocess` : Postprocessing option (choices `none`, `md2docx`, `md2html`; default `none`)
39+
40+
Example usage:
41+
42+
```bash
43+
# instantiate a template and postprocess to DOCX
44+
template-processor \\
45+
-i examples/demo-project/interfaceview.xml \\
46+
-d examples/demo-project/deploymentview.dv.xml \\
47+
-s data/parameters.csv \\
48+
-v TARGET=ASW \\
49+
-t data/ecss-template/ecss-e-st-40c_4_1_software_static_architecture.tmplt \\
50+
-o output \\
51+
-p md2docx
52+
```
2053

21-
TODO
54+
Notes:
55+
- The `-o/--output` directory will be used for writing generated files; templates may also copy or move generated assets (images) into that directory if supported by the template.
56+
- When using `md2docx` postprocessing, image paths inside the generated Markdown should be resolvable from the working directory or the output directory so images are embedded correctly in the produced DOCX.
2257

2358
## Frequently Asked Questions (FAQ)
2459

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
<%
2+
## Data Initialization
3+
# Get all functions
4+
5+
funcs = []
6+
def get_function_children(func):
7+
result = []
8+
if func.nested_functions:
9+
for nested in func.nested_functions:
10+
result.append(nested)
11+
result.extend(get_function_children(nested))
12+
return result
13+
14+
for func in interface_view.functions:
15+
funcs.append(func)
16+
funcs.extend(get_function_children(func))
17+
18+
funcs.sort(key=lambda f: f.name.lower())
19+
20+
# Get functions deployed to the target partition
21+
target_partition_name = values["TARGET"]
22+
23+
deployed_funcs = []
24+
target_partition = None
25+
for node in deployment_view.nodes:
26+
for partition in node.partitions:
27+
if partition.name == target_partition_name:
28+
target_partition = partition
29+
30+
deployed_func_names = [f.name for f in target_partition.functions]
31+
for fun in funcs:
32+
if fun.name in deployed_func_names:
33+
deployed_funcs.append(fun)
34+
35+
# Only leaf functions are deployed, so a correction for parents must be applied
36+
for func in funcs:
37+
if func.nested_functions:
38+
for nested in func.nested_functions:
39+
if nested in deployed_funcs and not func in deployed_funcs:
40+
deployed_funcs.append(func)
41+
deployed_func_names.append(func.name)
42+
43+
# Filter SDL functions only
44+
import os
45+
import subprocess
46+
import glob
47+
48+
sdl_funcs = [func for func in deployed_funcs if func.language and func.language.value == "SDL"]
49+
50+
# Generate SDL behavior diagrams using OpenGEODE
51+
def generate_sdl_images(func):
52+
"""Generate SDL images for a function using OpenGEODE"""
53+
func_lower = func.name.lower()
54+
images = []
55+
56+
# Try different path patterns for SDL/src directory
57+
# Pattern 1: work/{function}/SDL/src
58+
sdl_path_1 = f"work/{func_lower}/SDL/src"
59+
# Pattern 2: work/{function}/implem/{implementation}/SDL/src
60+
sdl_path_2_pattern = f"work/{func_lower}/implem/*/SDL/src"
61+
62+
sdl_paths = []
63+
if os.path.exists(sdl_path_1):
64+
sdl_paths.append(sdl_path_1)
65+
else:
66+
# Check for implementation-specific paths
67+
matching_paths = glob.glob(sdl_path_2_pattern)
68+
sdl_paths.extend(matching_paths)
69+
70+
for sdl_path in sdl_paths:
71+
if not os.path.exists(sdl_path):
72+
continue
73+
74+
# Find the system_structure.pr and function.pr files
75+
system_pr = os.path.join(sdl_path, "system_structure.pr")
76+
func_pr = os.path.join(sdl_path, f"{func_lower}.pr")
77+
78+
if not os.path.exists(system_pr) or not os.path.exists(func_pr):
79+
continue
80+
81+
# Generate images using OpenGEODE
82+
try:
83+
# Change to SDL/src directory to run opengeode
84+
original_dir = os.getcwd()
85+
86+
# Get absolute path to output directory before changing directories
87+
abs_output_dir = None
88+
if output_directory:
89+
abs_output_dir = os.path.abspath(output_directory)
90+
print(f"Output directory (absolute): {abs_output_dir}")
91+
print(f"Output directory exists: {os.path.exists(abs_output_dir)}")
92+
93+
# Get absolute path to SDL directory
94+
abs_sdl_path = os.path.abspath(sdl_path)
95+
96+
os.chdir(sdl_path)
97+
98+
# Run OpenGEODE to generate PNG images
99+
subprocess.run(
100+
["opengeode", "--png", "system_structure.pr", f"{func_lower}.pr"],
101+
check=False,
102+
capture_output=True
103+
)
104+
105+
# Find all generated PNG files and move them to output directory
106+
png_files = glob.glob("*.png")
107+
print(f"Found {len(png_files)} PNG files in {abs_sdl_path}")
108+
109+
for png_file in sorted(png_files):
110+
# Extract caption from filename (remove extension)
111+
caption = os.path.splitext(png_file)[0].replace("-", " ").replace("_", " ")
112+
113+
# If output_directory is specified, copy the image there
114+
if abs_output_dir and os.path.exists(abs_output_dir):
115+
import shutil
116+
# Since we're in the sdl_path directory, png_file is in current dir
117+
src_path = png_file
118+
# Create unique filename with function name to avoid collisions
119+
dest_filename = f"{func_lower}_{png_file}"
120+
dest_path = os.path.join(abs_output_dir, dest_filename)
121+
print(f"Copying {src_path} to {dest_path}")
122+
shutil.copy2(src_path, dest_path)
123+
# Use only the filename (no path) for markdown reference
124+
images.append((dest_filename, caption))
125+
else:
126+
# Fallback: use relative path from original working directory
127+
abs_img_path = os.path.join(abs_sdl_path, png_file)
128+
rel_path = os.path.relpath(abs_img_path, original_dir)
129+
images.append((rel_path, caption))
130+
131+
os.chdir(original_dir)
132+
except Exception as e:
133+
# If OpenGEODE fails, just continue
134+
if 'original_dir' in locals():
135+
os.chdir(original_dir)
136+
pass
137+
138+
return images
139+
140+
# Generate images for all SDL functions
141+
func_images = {}
142+
for func in sdl_funcs:
143+
images = generate_sdl_images(func)
144+
if images:
145+
func_images[func.name] = images
146+
147+
%>
148+
149+
This section describes the behaviour of software components implemented in SDL.
150+
151+
The behaviour of each SDL function is documented using state machine diagrams generated from the SDL implementation.
152+
153+
% if not sdl_funcs:
154+
*No SDL functions found in the ${target_partition_name} partition.*
155+
% else:
156+
## SDL Functions
157+
158+
The following functions are implemented in SDL and their behaviour is documented below:
159+
160+
% for func in sdl_funcs:
161+
${"###"} ${func.name}
162+
163+
**Description:** ${func.comment if func.comment else "No description available."}
164+
165+
% if func.name in func_images and func_images[func.name]:
166+
**Behavioural Diagrams:**
167+
168+
The following diagrams illustrate the behaviour of the ${func.name} function:
169+
170+
% for (img_path, caption) in func_images[func.name]:
171+
![${func.name}](${img_path} "${caption}")
172+
173+
% endfor
174+
% else:
175+
*No SDL diagrams available for this function. The function may not have SDL source files in the expected location, or OpenGEODE image generation was not successful.*
176+
% endif
177+
178+
% endfor
179+
% endif

0 commit comments

Comments
 (0)