Initial commit
This commit is contained in:
114
skills/ontological-documentation/scripts/README.md
Normal file
114
skills/ontological-documentation/scripts/README.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Ontological Documentation Scripts
|
||||
|
||||
This directory contains utility scripts for automated concept extraction and diagram generation.
|
||||
|
||||
## Scripts
|
||||
|
||||
### extract_concepts.py
|
||||
|
||||
Analyzes codebases to extract domain concepts, entities, and relationships for building ontological documentation.
|
||||
|
||||
**Features:**
|
||||
- Supports Python and JavaScript/TypeScript
|
||||
- Extracts classes, functions, inheritance relationships, and imports
|
||||
- Builds ontological structure with relationships (is_a, part_of, depends_on, associates_with)
|
||||
- Generates JSON ontology representation
|
||||
- Creates Mermaid diagrams
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Analyze a single file
|
||||
python extract_concepts.py /path/to/file.py
|
||||
|
||||
# Analyze a directory
|
||||
python extract_concepts.py /path/to/codebase
|
||||
|
||||
# Save output to file
|
||||
python extract_concepts.py /path/to/codebase > ontology.json
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- JSON ontology structure
|
||||
- Mermaid diagram representation
|
||||
|
||||
### generate_ontology_diagram.py
|
||||
|
||||
Generates visual representations of ontologies in various formats.
|
||||
|
||||
**Features:**
|
||||
- Supports multiple diagram formats (Mermaid, PlantUML, GraphViz DOT, JSON-LD)
|
||||
- Customizable relationship symbols
|
||||
- Semantic web compatibility (JSON-LD output)
|
||||
- Styled diagrams with concept type differentiation
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Generate all formats
|
||||
python generate_ontology_diagram.py ontology.json
|
||||
|
||||
# Generate specific format
|
||||
python generate_ontology_diagram.py ontology.json --format mermaid
|
||||
|
||||
# Specify output directory
|
||||
python generate_ontology_diagram.py ontology.json --output ./diagrams
|
||||
|
||||
# Available formats: mermaid, plantuml, dot, json-ld, all
|
||||
```
|
||||
|
||||
**Output Examples:**
|
||||
|
||||
Mermaid:
|
||||
```bash
|
||||
python generate_ontology_diagram.py ontology.json --format mermaid
|
||||
# Creates: ontology_mermaid.md
|
||||
```
|
||||
|
||||
PlantUML:
|
||||
```bash
|
||||
python generate_ontology_diagram.py ontology.json --format plantuml
|
||||
# Creates: ontology_plantuml.puml
|
||||
```
|
||||
|
||||
GraphViz DOT:
|
||||
```bash
|
||||
python generate_ontology_diagram.py ontology.json --format dot
|
||||
# Creates: ontology.dot
|
||||
```
|
||||
|
||||
JSON-LD:
|
||||
```bash
|
||||
python generate_ontology_diagram.py ontology.json --format json-ld
|
||||
# Creates: ontology_jsonld.json
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
Both scripts use only Python standard library modules:
|
||||
- `ast` - Python AST parsing
|
||||
- `re` - Regular expressions
|
||||
- `json` - JSON processing
|
||||
- `pathlib` - Path handling
|
||||
- `argparse` - Command-line argument parsing
|
||||
|
||||
No additional dependencies required!
|
||||
|
||||
## Example Workflow
|
||||
|
||||
```bash
|
||||
# 1. Extract concepts from codebase
|
||||
python extract_concepts.py /path/to/codebase > ontology.json
|
||||
|
||||
# 2. Generate diagrams
|
||||
python generate_ontology_diagram.py ontology.json --output ./docs/diagrams
|
||||
|
||||
# 3. Review generated documentation
|
||||
ls ./docs/diagrams/
|
||||
# ontology_mermaid.md
|
||||
# ontology_plantuml.puml
|
||||
# ontology.dot
|
||||
# ontology_jsonld.json
|
||||
```
|
||||
|
||||
## Integration with Skill
|
||||
|
||||
These scripts support the main [SKILL.md](../SKILL.md) by providing automated tools for concept extraction and visualization. Use them to bootstrap your ontological documentation process.
|
||||
259
skills/ontological-documentation/scripts/extract_concepts.py
Executable file
259
skills/ontological-documentation/scripts/extract_concepts.py
Executable file
@@ -0,0 +1,259 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Concept Extraction Script for Ontological Documentation
|
||||
|
||||
This script analyzes codebases to extract domain concepts, entities, and relationships
|
||||
for building ontological documentation. It supports multiple programming languages
|
||||
and can identify inheritance hierarchies, composition patterns, and semantic relationships.
|
||||
"""
|
||||
|
||||
import ast
|
||||
import re
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Set, Tuple, Any
|
||||
from collections import defaultdict
|
||||
|
||||
class ConceptExtractor:
|
||||
"""Extracts ontological concepts from source code."""
|
||||
|
||||
def __init__(self):
|
||||
self.concepts = defaultdict(dict)
|
||||
self.relationships = defaultdict(list)
|
||||
self.taxonomies = defaultdict(list)
|
||||
|
||||
def extract_from_python(self, file_path: Path) -> Dict[str, Any]:
|
||||
"""Extract concepts from Python source code."""
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
tree = ast.parse(f.read())
|
||||
|
||||
visitor = ClassVisitor()
|
||||
visitor.visit(tree)
|
||||
|
||||
return {
|
||||
'classes': visitor.classes,
|
||||
'inheritance': visitor.inheritance,
|
||||
'imports': visitor.imports,
|
||||
'functions': visitor.functions
|
||||
}
|
||||
except Exception as e:
|
||||
return {'error': str(e)}
|
||||
|
||||
def extract_from_javascript(self, file_path: Path) -> Dict[str, Any]:
|
||||
"""Extract concepts from JavaScript/TypeScript source code."""
|
||||
concepts = {
|
||||
'classes': [],
|
||||
'interfaces': [],
|
||||
'functions': [],
|
||||
'imports': []
|
||||
}
|
||||
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Extract class declarations
|
||||
class_pattern = r'(?:class|interface)\s+(\w+)(?:\s+extends\s+(\w+))?'
|
||||
for match in re.finditer(class_pattern, content):
|
||||
class_name = match.group(1)
|
||||
parent_class = match.group(2)
|
||||
concepts['classes'].append({
|
||||
'name': class_name,
|
||||
'parent': parent_class,
|
||||
'type': 'class' if 'class' in match.group(0) else 'interface'
|
||||
})
|
||||
|
||||
# Extract function declarations
|
||||
func_pattern = r'(?:function\s+(\w+)|const\s+(\w+)\s*=\s*(?:\([^)]*\)\s*)?=>|(\w+)\s*:\s*\([^)]*\)\s*=>)'
|
||||
for match in re.finditer(func_pattern, content):
|
||||
func_name = match.group(1) or match.group(2) or match.group(3)
|
||||
if func_name:
|
||||
concepts['functions'].append({'name': func_name})
|
||||
|
||||
# Extract imports
|
||||
import_pattern = r'import\s+.*?from\s+["\']([^"\']+)["\']'
|
||||
for match in re.finditer(import_pattern, content):
|
||||
concepts['imports'].append({'source': match.group(1)})
|
||||
|
||||
except Exception as e:
|
||||
concepts['error'] = str(e)
|
||||
|
||||
return concepts
|
||||
|
||||
def build_ontology(self, extracted_data: List[Dict[str, Any]]) -> Dict[str, Any]:
|
||||
"""Build ontological structure from extracted data."""
|
||||
ontology = {
|
||||
'concepts': {},
|
||||
'relationships': {
|
||||
'is_a': [], # inheritance
|
||||
'part_of': [], # composition
|
||||
'depends_on': [], # dependencies
|
||||
'associates_with': [] # loose associations
|
||||
},
|
||||
'taxonomies': {}
|
||||
}
|
||||
|
||||
all_classes = []
|
||||
all_functions = []
|
||||
all_imports = []
|
||||
|
||||
# Collect all entities
|
||||
for data in extracted_data:
|
||||
if 'classes' in data:
|
||||
all_classes.extend(data['classes'])
|
||||
if 'functions' in data:
|
||||
all_functions.extend(data['functions'])
|
||||
if 'imports' in data:
|
||||
all_imports.extend(data['imports'])
|
||||
|
||||
# Build concepts
|
||||
for cls in all_classes:
|
||||
if isinstance(cls, dict):
|
||||
concept_name = cls.get('name', str(cls))
|
||||
ontology['concepts'][concept_name] = {
|
||||
'type': 'class',
|
||||
'properties': cls
|
||||
}
|
||||
|
||||
# Build inheritance relationships
|
||||
parent = cls.get('parent')
|
||||
if parent:
|
||||
ontology['relationships']['is_a'].append({
|
||||
'subject': concept_name,
|
||||
'object': parent
|
||||
})
|
||||
|
||||
for func in all_functions:
|
||||
if isinstance(func, dict):
|
||||
func_name = func.get('name', str(func))
|
||||
ontology['concepts'][func_name] = {
|
||||
'type': 'function',
|
||||
'properties': func
|
||||
}
|
||||
|
||||
return ontology
|
||||
|
||||
def generate_mermaid_diagram(self, ontology: Dict[str, Any]) -> str:
|
||||
"""Generate Mermaid diagram from ontology."""
|
||||
lines = ["graph TD"]
|
||||
|
||||
# Add concepts as nodes
|
||||
for concept_name, concept_data in ontology['concepts'].items():
|
||||
concept_type = concept_data.get('type', 'concept')
|
||||
if concept_type == 'class':
|
||||
lines.append(f" {concept_name}[({concept_name})]")
|
||||
else:
|
||||
lines.append(f" {concept_name}[{concept_name}]")
|
||||
|
||||
# Add relationships
|
||||
for rel_type, relationships in ontology['relationships'].items():
|
||||
for rel in relationships:
|
||||
subject = rel['subject']
|
||||
obj = rel['object']
|
||||
|
||||
if rel_type == 'is_a':
|
||||
lines.append(f" {subject} --|> {obj}")
|
||||
elif rel_type == 'part_of':
|
||||
lines.append(f" {subject} --* {obj}")
|
||||
elif rel_type == 'depends_on':
|
||||
lines.append(f" {subject} -.-> {obj}")
|
||||
else:
|
||||
lines.append(f" {subject} --- {obj}")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
class ClassVisitor(ast.NodeVisitor):
|
||||
"""AST visitor for Python class analysis."""
|
||||
|
||||
def __init__(self):
|
||||
self.classes = []
|
||||
self.inheritance = []
|
||||
self.imports = []
|
||||
self.functions = []
|
||||
|
||||
def visit_ClassDef(self, node):
|
||||
class_info = {
|
||||
'name': node.name,
|
||||
'bases': [base.id for base in node.bases if hasattr(base, 'id')],
|
||||
'methods': [],
|
||||
'line_number': node.lineno
|
||||
}
|
||||
|
||||
for item in node.body:
|
||||
if isinstance(item, ast.FunctionDef):
|
||||
class_info['methods'].append({
|
||||
'name': item.name,
|
||||
'args': [arg.arg for arg in item.args.args],
|
||||
'line_number': item.lineno
|
||||
})
|
||||
|
||||
self.classes.append(class_info)
|
||||
|
||||
# Track inheritance
|
||||
for base in node.bases:
|
||||
if hasattr(base, 'id'):
|
||||
self.inheritance.append({
|
||||
'child': node.name,
|
||||
'parent': base.id
|
||||
})
|
||||
|
||||
self.generic_visit(node)
|
||||
|
||||
def visit_Import(self, node):
|
||||
for alias in node.names:
|
||||
self.imports.append({
|
||||
'module': alias.name,
|
||||
'alias': alias.asname
|
||||
})
|
||||
self.generic_visit(node)
|
||||
|
||||
def visit_FunctionDef(self, node):
|
||||
func_info = {
|
||||
'name': node.name,
|
||||
'args': [arg.arg for arg in node.args.args],
|
||||
'line_number': node.lineno
|
||||
}
|
||||
self.functions.append(func_info)
|
||||
self.generic_visit(node)
|
||||
|
||||
def main():
|
||||
"""Main function to run concept extraction."""
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python extract_concepts.py <file_or_directory_path>")
|
||||
sys.exit(1)
|
||||
|
||||
path = Path(sys.argv[1])
|
||||
extractor = ConceptExtractor()
|
||||
extracted_data = []
|
||||
|
||||
if path.is_file():
|
||||
if path.suffix == '.py':
|
||||
data = extractor.extract_from_python(path)
|
||||
extracted_data.append(data)
|
||||
elif path.suffix in ['.js', '.ts', '.jsx', '.tsx']:
|
||||
data = extractor.extract_from_javascript(path)
|
||||
extracted_data.append(data)
|
||||
elif path.is_dir():
|
||||
for file_path in path.rglob('*'):
|
||||
if file_path.is_file():
|
||||
if file_path.suffix == '.py':
|
||||
data = extractor.extract_from_python(file_path)
|
||||
extracted_data.append(data)
|
||||
elif file_path.suffix in ['.js', '.ts', '.jsx', '.tsx']:
|
||||
data = extractor.extract_from_javascript(file_path)
|
||||
extracted_data.append(data)
|
||||
|
||||
ontology = extractor.build_ontology(extracted_data)
|
||||
|
||||
# Output as JSON
|
||||
print(json.dumps(ontology, indent=2))
|
||||
|
||||
# Also generate Mermaid diagram
|
||||
diagram = extractor.generate_mermaid_diagram(ontology)
|
||||
print("\n--- Mermaid Diagram ---")
|
||||
print(diagram)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
288
skills/ontological-documentation/scripts/generate_ontology_diagram.py
Executable file
288
skills/ontological-documentation/scripts/generate_ontology_diagram.py
Executable file
@@ -0,0 +1,288 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Ontology Diagram Generator
|
||||
|
||||
This script generates visual representations of ontologies in various formats
|
||||
including Mermaid, PlantUML, GraphViz DOT, and JSON-LD for semantic web applications.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import argparse
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any, Optional
|
||||
|
||||
class OntologyDiagramGenerator:
|
||||
"""Generates diagrams for ontological documentation."""
|
||||
|
||||
def __init__(self):
|
||||
self.relationship_symbols = {
|
||||
'is_a': '--|>', # Inheritance
|
||||
'part_of': '--*', # Composition
|
||||
'depends_on': '-.->', # Dependency
|
||||
'associates_with': '---', # Association
|
||||
'instance_of': '..>' # Instantiation
|
||||
}
|
||||
|
||||
def generate_mermaid(self, ontology: Dict[str, Any]) -> str:
|
||||
"""Generate Mermaid diagram from ontology."""
|
||||
lines = ["graph TD"]
|
||||
lines.append(" %% Ontology Diagram")
|
||||
lines.append(" %% Generated from ontological documentation")
|
||||
|
||||
# Add styling
|
||||
lines.extend([
|
||||
" classDef concept fill:#e1f5fe,stroke:#01579b,stroke-width:2px",
|
||||
" classDef class fill:#f3e5f5,stroke:#4a148c,stroke-width:2px",
|
||||
" classDef interface fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px",
|
||||
" classDef function fill:#fff3e0,stroke:#e65100,stroke-width:2px"
|
||||
])
|
||||
|
||||
# Add concepts as nodes
|
||||
concept_classes = {}
|
||||
for concept_name, concept_data in ontology['concepts'].items():
|
||||
concept_type = concept_data.get('type', 'concept')
|
||||
|
||||
if concept_type == 'class':
|
||||
lines.append(f" {self._safe_name(concept_name)}[({concept_name})]")
|
||||
concept_classes[concept_name] = 'class'
|
||||
elif concept_type == 'interface':
|
||||
lines.append(f" {self._safe_name(concept_name)}[{{interface}}{concept_name}]")
|
||||
concept_classes[concept_name] = 'interface'
|
||||
elif concept_type == 'function':
|
||||
lines.append(f" {self._safe_name(concept_name)}[{concept_name}()]")
|
||||
concept_classes[concept_name] = 'function'
|
||||
else:
|
||||
lines.append(f" {self._safe_name(concept_name)}[{concept_name}]")
|
||||
concept_classes[concept_name] = 'concept'
|
||||
|
||||
# Add relationships
|
||||
for rel_type, relationships in ontology['relationships'].items():
|
||||
symbol = self.relationship_symbols.get(rel_type, '---')
|
||||
for rel in relationships:
|
||||
subject = self._safe_name(rel['subject'])
|
||||
obj = self._safe_name(rel['object'])
|
||||
label = rel.get('label', rel_type.replace('_', ' ').title())
|
||||
lines.append(f" {subject} {symbol} {obj}")
|
||||
|
||||
# Apply classes
|
||||
for concept_name, css_class in concept_classes.items():
|
||||
lines.append(f" class {self._safe_name(concept_name)} {css_class}")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
def generate_plantuml(self, ontology: Dict[str, Any]) -> str:
|
||||
"""Generate PlantUML diagram from ontology."""
|
||||
lines = ["@startuml Ontology"]
|
||||
lines.append("!theme plain")
|
||||
lines.append("skinparam classAttributeIconSize 0")
|
||||
|
||||
# Add concepts as classes
|
||||
for concept_name, concept_data in ontology['concepts'].items():
|
||||
concept_type = concept_data.get('type', 'concept')
|
||||
|
||||
if concept_type == 'class':
|
||||
lines.append(f"class {concept_name} {{}}")
|
||||
elif concept_type == 'interface':
|
||||
lines.append(f"interface {concept_name} {{}}")
|
||||
elif concept_type == 'function':
|
||||
lines.append(f"object {concept_name} {{}}")
|
||||
else:
|
||||
lines.append(f"abstract {concept_name} {{}}")
|
||||
|
||||
lines.append("") # Empty line for separation
|
||||
|
||||
# Add relationships
|
||||
for rel_type, relationships in ontology['relationships'].items():
|
||||
for rel in relationships:
|
||||
subject = rel['subject']
|
||||
obj = rel['object']
|
||||
|
||||
if rel_type == 'is_a':
|
||||
lines.append(f"{subject} <|-- {obj}")
|
||||
elif rel_type == 'part_of':
|
||||
lines.append(f"{subject} *-- {obj}")
|
||||
elif rel_type == 'depends_on':
|
||||
lines.append(f"{subject} ..> {obj}")
|
||||
else:
|
||||
lines.append(f"{subject} -- {obj}")
|
||||
|
||||
lines.append("@enduml")
|
||||
return "\n".join(lines)
|
||||
|
||||
def generate_dot(self, ontology: Dict[str, Any]) -> str:
|
||||
"""Generate GraphViz DOT diagram from ontology."""
|
||||
lines = ["digraph Ontology {"]
|
||||
lines.append(' rankdir=TB;')
|
||||
lines.append(' node [shape=box, style=filled];')
|
||||
lines.append(' edge [fontsize=10];')
|
||||
|
||||
# Add concepts as nodes
|
||||
for concept_name, concept_data in ontology['concepts'].items():
|
||||
concept_type = concept_data.get('type', 'concept')
|
||||
|
||||
# Set colors based on type
|
||||
if concept_type == 'class':
|
||||
color = "lightpurple"
|
||||
elif concept_type == 'interface':
|
||||
color = "lightgreen"
|
||||
elif concept_type == 'function':
|
||||
color = "lightorange"
|
||||
else:
|
||||
color = "lightblue"
|
||||
|
||||
lines.append(f' "{concept_name}" [label="{concept_name}", fillcolor="{color}"];')
|
||||
|
||||
lines.append("") # Empty line for separation
|
||||
|
||||
# Add relationships
|
||||
for rel_type, relationships in ontology['relationships'].items():
|
||||
for rel in relationships:
|
||||
subject = rel['subject']
|
||||
obj = rel['object']
|
||||
label = rel.get('label', rel_type.replace('_', ' ').title())
|
||||
|
||||
# Set arrow styles based on relationship type
|
||||
if rel_type == 'is_a':
|
||||
arrow = 'empty'
|
||||
elif rel_type == 'part_of':
|
||||
arrow = 'diamond'
|
||||
elif rel_type == 'depends_on':
|
||||
arrow = 'dashed'
|
||||
else:
|
||||
arrow = 'normal'
|
||||
|
||||
lines.append(f' "{subject}" -> "{obj}" [label="{label}", arrowhead={arrow}];')
|
||||
|
||||
lines.append("}")
|
||||
return "\n".join(lines)
|
||||
|
||||
def generate_json_ld(self, ontology: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Generate JSON-LD representation of ontology."""
|
||||
context = {
|
||||
"@context": {
|
||||
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
|
||||
"owl": "http://www.w3.org/2002/07/owl#",
|
||||
"Concept": "rdfs:Class",
|
||||
"subClassOf": {
|
||||
"@id": "rdfs:subClassOf",
|
||||
"@type": "@id"
|
||||
},
|
||||
"partOf": {
|
||||
"@id": "http://example.org/ontology#partOf",
|
||||
"@type": "@id"
|
||||
},
|
||||
"dependsOn": {
|
||||
"@id": "http://example.org/ontology#dependsOn",
|
||||
"@type": "@id"
|
||||
}
|
||||
},
|
||||
"@graph": []
|
||||
}
|
||||
|
||||
# Add concepts
|
||||
for concept_name, concept_data in ontology['concepts'].items():
|
||||
concept_entry = {
|
||||
"@id": f"http://example.org/ontology#{concept_name}",
|
||||
"@type": ["Concept"]
|
||||
}
|
||||
|
||||
concept_type = concept_data.get('type', 'concept')
|
||||
if concept_type == 'class':
|
||||
concept_entry["@type"].append("owl:Class")
|
||||
elif concept_type == 'interface':
|
||||
concept_entry["@type"].append("owl:Class")
|
||||
|
||||
context["@graph"].append(concept_entry)
|
||||
|
||||
# Add relationships
|
||||
for rel_type, relationships in ontology['relationships'].items():
|
||||
for rel in relationships:
|
||||
subject = rel['subject']
|
||||
obj = rel['object']
|
||||
|
||||
if rel_type == 'is_a':
|
||||
context["@graph"].append({
|
||||
"@id": f"http://example.org/ontology#{subject}",
|
||||
"subClassOf": f"http://example.org/ontology#{obj}"
|
||||
})
|
||||
elif rel_type == 'part_of':
|
||||
context["@graph"].append({
|
||||
"@id": f"http://example.org/ontology#{subject}",
|
||||
"partOf": f"http://example.org/ontology#{obj}"
|
||||
})
|
||||
elif rel_type == 'depends_on':
|
||||
context["@graph"].append({
|
||||
"@id": f"http://example.org/ontology#{subject}",
|
||||
"dependsOn": f"http://example.org/ontology#{obj}"
|
||||
})
|
||||
|
||||
return context
|
||||
|
||||
def _safe_name(self, name: str) -> str:
|
||||
"""Convert name to safe identifier for diagram formats."""
|
||||
# Replace special characters and spaces with underscores
|
||||
return re.sub(r'[^a-zA-Z0-9_]', '_', name)
|
||||
|
||||
def load_ontology(file_path: Path) -> Dict[str, Any]:
|
||||
"""Load ontology from JSON file."""
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
|
||||
def main():
|
||||
"""Main function to generate diagrams."""
|
||||
parser = argparse.ArgumentParser(description='Generate ontology diagrams')
|
||||
parser.add_argument('ontology_file', help='Path to ontology JSON file')
|
||||
parser.add_argument('--format', choices=['mermaid', 'plantuml', 'dot', 'json-ld', 'all'],
|
||||
default='all', help='Diagram format to generate')
|
||||
parser.add_argument('--output', help='Output directory (default: current directory)')
|
||||
args = parser.parse_args()
|
||||
|
||||
ontology_path = Path(args.ontology_file)
|
||||
if not ontology_path.exists():
|
||||
print(f"Error: Ontology file '{ontology_path}' not found")
|
||||
sys.exit(1)
|
||||
|
||||
ontology = load_ontology(ontology_path)
|
||||
generator = OntologyDiagramGenerator()
|
||||
|
||||
output_dir = Path(args.output) if args.output else Path('.')
|
||||
output_dir.mkdir(exist_ok=True)
|
||||
|
||||
formats_to_generate = ['mermaid', 'plantuml', 'dot', 'json-ld'] if args.format == 'all' else [args.format]
|
||||
|
||||
for format_type in formats_to_generate:
|
||||
if format_type == 'mermaid':
|
||||
diagram = generator.generate_mermaid(ontology)
|
||||
output_file = output_dir / f"{ontology_path.stem}_mermaid.md"
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(f"# {ontology_path.stem} Ontology Diagram\n\n")
|
||||
f.write("```mermaid\n")
|
||||
f.write(diagram)
|
||||
f.write("\n```")
|
||||
print(f"Generated Mermaid diagram: {output_file}")
|
||||
|
||||
elif format_type == 'plantuml':
|
||||
diagram = generator.generate_plantuml(ontology)
|
||||
output_file = output_dir / f"{ontology_path.stem}_plantuml.puml"
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(diagram)
|
||||
print(f"Generated PlantUML diagram: {output_file}")
|
||||
|
||||
elif format_type == 'dot':
|
||||
diagram = generator.generate_dot(ontology)
|
||||
output_file = output_dir / f"{ontology_path.stem}.dot"
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(diagram)
|
||||
print(f"Generated GraphViz DOT diagram: {output_file}")
|
||||
|
||||
elif format_type == 'json-ld':
|
||||
json_ld = generator.generate_json_ld(ontology)
|
||||
output_file = output_dir / f"{ontology_path.stem}_jsonld.json"
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(json_ld, f, indent=2)
|
||||
print(f"Generated JSON-LD: {output_file}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user