Last active
July 16, 2023 12:40
-
-
Save M0r13n/927f97c591d13f0d8bb1665760514f4b to your computer and use it in GitHub Desktop.
Read Sparx Enterprise Architect files (.qea) using SQLite and SQLAlchemy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Requires sqlalchemy and sqlalchemy_mixins. Install via pip | |
""" | |
import pathlib | |
import typing | |
from sqlalchemy import ForeignKey, Text, create_engine, Column, Integer, String | |
from sqlalchemy.orm import create_session, relationship, declarative_base | |
from sqlalchemy_mixins import ReprMixin | |
db_file = pathlib.Path(__file__).parent.joinpath('model.qea') | |
engine = create_engine(f'sqlite:////{str(db_file.absolute())}') | |
session = create_session(engine) | |
Base = declarative_base() | |
class BaseModel(Base, ReprMixin): | |
""" | |
This is the base model that every Sqlalchemy model class should inherit from. | |
""" | |
__abstract__ = True | |
pass | |
class SQLiteSequence(BaseModel): | |
__tablename__ = 'sqlite_sequence' | |
name = Column(String, primary_key=True) | |
seq = Column(Integer) | |
class Diagram(BaseModel): | |
# Declarative meta data for sql-alchemy | |
__tablename__ = 't_diagram' | |
__repr_attrs__ = ['name'] | |
diagram_id = Column(Integer, primary_key=True) | |
name = Column(Text) | |
diagram_type = Column(Text) | |
# Relations | |
package_id = Column(Integer, ForeignKey('t_package.package_id')) | |
package = relationship('Package', back_populates='diagrams', ) | |
parentid = Column(Integer, ForeignKey('t_diagram.diagram_id')) | |
parent = relationship('Diagram', remote_side=[diagram_id]) | |
objects = relationship('Object', back_populates='diagram') | |
class Package(BaseModel): | |
# Declarative meta data for sql-alchemy | |
__tablename__ = 't_package' | |
__repr_attrs__ = ['name'] | |
package_id = Column(Integer, primary_key=True) | |
name = Column(Text) | |
parent_id = Column(Integer, ForeignKey('t_package.package_id')) | |
parent = relationship('Package', remote_side=[package_id]) | |
objects = relationship( | |
'Object', back_populates='package') | |
diagrams = relationship( | |
'Diagram', back_populates='package') | |
class Object(BaseModel): | |
# Declarative meta data for sql-alchemy | |
__tablename__ = 't_object' | |
__repr_attrs__ = ['name', 'classifier', 'parent'] | |
object_id = Column(Integer, primary_key=True) | |
object_type = Column(Text) | |
name = Column(Text) | |
note = Column(Text) | |
multiplicity = Column(Text) | |
cardinality = Column(Text) | |
# Relations | |
parentid = Column(Integer, ForeignKey('t_object.object_id')) | |
parent = relationship('Object', remote_side=[object_id]) | |
diagram_id = Column(Integer, ForeignKey('t_diagram.diagram_id')) | |
diagram = relationship('Diagram', back_populates='objects') | |
package_id = Column(Integer, ForeignKey('t_package.package_id')) | |
package = relationship('Package', back_populates='objects') | |
classifier = Column(Integer) | |
class Connector(BaseModel): | |
# Declarative meta data for sql-alchemy | |
__tablename__ = 't_connector' | |
__repr_attrs__ = ['name', 'connector_type'] | |
connector_id = Column(Integer, primary_key=True) | |
name = Column(Text) | |
direction = Column(Text) | |
connector_type = Column(Text) | |
sourcerole = Column(Text) | |
# Relations | |
start_object_id = Column(Integer, ForeignKey('t_object.object_id')) | |
end_object_id = Column(Integer, ForeignKey('t_object.object_id')) | |
start = relationship('Object', backref='leaving', | |
foreign_keys=[start_object_id]) | |
end = relationship('Object', backref='incoming', | |
foreign_keys=[end_object_id]) | |
# Load data from the table | |
packages = session.query(Package).all() | |
for pkg in packages: | |
print(pkg) | |
diagram: Diagram | |
for diagram in pkg.diagrams: | |
print('\t', diagram) | |
obj: Object | |
for obj in pkg.objects: | |
print('\t', obj) | |
print('\t', 'Leaving:') | |
for conn in obj.leaving: | |
print('\t\t\t', conn) | |
print('\t', 'Incoming:') | |
for conn in obj.incoming: | |
print('\t\t\t', conn) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment