3.2. Project file format

OrmFactory supports two project file formats:

  • .ormfactory — a single XML file containing the complete project.
  • .0fproj — a directory-based project format where the project is split into multiple files.

Both formats represent the same logical project structure. The difference is only how the project is stored on disk.

The multi-file format is designed to make project resources easier to work with individually and to integrate with Git.

Single-File Format

A single-file project uses the .ormfactory extension:

MyProject.ormfactory

The file contains the complete project model as a single XML document:

<?xml version="1.0" encoding="utf-8"?>
<Project Name="MyProject" Software="OrmFactory.com">
	...
</Project>

Databases, schemas, tables, layouts, connections, generators, and profiles are all stored inside this document.

The single-file format is convenient when the complete project should be treated as one file.

Multi-File Format

A multi-file project uses the .0fproj extension as its project file and stores the rest of the project in a directory structure.

For example:

MyProject/
├── .gitattributes
├── MyProject.0fproj
├── connections/
│   └── local.connection
├── generators/
│   └── Python.generator
├── layouts/
│   └── Main.layout
└── Schemas.database/
	├── Schemas.database
	└── erp.schema/
		├── erp.schema
		├── Customers.table
		└── Orders.table

The project file contains project-level information. Other project resources are stored in their own files.

The exact file names depend on the corresponding project object names. OrmFactory converts object names to file-system-safe names before adding the appropriate extension.

Project File

The main .0fproj file represents the project itself.

For example:

<?xml version="1.0" encoding="utf-8"?>
<Project Name="MyProject" Software="ormfactory.com">
	<Profile Name="local">
		<Database Name="Schemas"
			Connection="local" />
	</Profile>
</Project>

Project-level information such as Profiles is stored here.

Databases, layouts, connections, and generators are stored in their corresponding files and directories instead of being embedded in the main project file.

Connections

Each project connection is stored in the connections directory:

connections/
├── local.connection
└── production.connection

A connection file contains a Connection element:

<?xml version="1.0" encoding="utf-8"?>
<Connection Name="local"
	DataBaseType="MySql"
	ServerHost="localhost"
	ServerPort="3306"
	UserName="user"
	Database="Schemas" />

The exact attributes depend on the database type and connection settings.

Common connection properties include:

  • database type;
  • server host;
  • server port;
  • user name;
  • password;
  • database name;
  • optional SSH settings.

Some database types add their own properties.

For example, SQL Server connections can contain authentication and encryption settings, while O-Bridge connections can contain bridge and Oracle-specific settings.

Generators

Each generator is stored as a separate file in the generators directory:

generators/
├── Python.generator
└── TypeScript.generator

A generator file contains the complete generator configuration:

<?xml version="1.0" encoding="utf-8"?>
<Generator Name="Python"
	Type="Python"
	Filename="generator.py"
	NameStyle="CamelCase">
	...
</Generator>

Partial-generation settings and generator arguments are stored inside the same file.

The generator script itself is separate from the .generator file. The generator configuration stores the filename or path used to locate the script.

Layouts

Each layout is stored separately in the layouts directory:

layouts/
├── Main.layout
└── Orders.layout

A layout file contains the layout and references to the tables displayed on it:

<?xml version="1.0" encoding="utf-8"?>
<Layout Name="Main">
	<Table Name="erp.Orders"
		Database="Schemas"
		Point="-145,784" />
	<Table Name="erp.Customers"
		Database="Schemas"
		Point="320,784" />
</Layout>

The Table elements in a layout are references to existing tables. They do not contain copies of the table definitions.

The Name attribute contains the schema-qualified table name:

Schema.Table

The database is specified separately by the Database attribute.

This keeps the reference unambiguous even when database names contain dots.

Databases

Each Database has its own directory:

Schemas.database/
├── Schemas.database
└── erp.schema/
	├── erp.schema
	├── Customers.table
	└── Orders.table

The directory name is the file-system-safe database name followed by .database.

The database file has the same base name:

Schemas.database/
└── Schemas.database

It contains the database-level information:

<?xml version="1.0" encoding="utf-8"?>
<Database Name="Schemas"
	Type="MySql" />

If the database has a migration generator, it is stored in the same file:

<Database Name="Schemas"
	Type="MySql">
	<MigrationGenerator Filename="migrations.py" />
</Database>

Schemas

Each schema has its own directory inside the database directory:

Schemas.database/
└── erp.schema/
	├── erp.schema
	├── Customers.table
	└── Orders.table

The schema directory and schema file use the same file-system-safe name.

The schema file contains the schema-level information:

<?xml version="1.0" encoding="utf-8"?>
<Schema Name="erp"
	Comment="ERP tables" />

Tables

Each table is stored as a .table file inside its schema directory:

erp.schema/
├── erp.schema
├── Customers.table
└── Orders.table

A table file contains the complete definition of the table:

<?xml version="1.0" encoding="utf-8"?>
<Table Name="Orders"
	ClassName="Order"
	RepositoryName="Orders">
	<Column Name="Id"
		Type="int"
		AutoIncrement="true" />

	<Column Name="CustomerId"
		Type="int" />

	<PrimaryKey Name="PK_Orders"
		Columns="Id" />

	<ForeignKey Name="FK_Orders_Customers"
		FromColumn="CustomerId"
		ToTable="Customers"
		ToColumn="Id" />
</Table>

Columns, keys, foreign keys, indexes, unique constraints, parameters, and named rows remain inside the table file. They are not split into additional files.

This makes a table an atomic project resource from the file-system perspective.

File Names

OrmFactory derives file and directory names from object names using a filesystem-safe naming function. The resulting name may differ from the original object name if it contains characters that are not suitable for file names or otherwise requires normalization.

The original object name is always preserved in the XML Name attribute. The file or directory name is only used to identify the corresponding project resource on disk.

For example:

Database name:  Schemas
Schema name:    erp
Table name:     Orders

becomes:

Schemas.database/
└── erp.schema/
	└── Orders.table

The original object name remains inside the XML:

<Database Name="Schemas" ... />
<Schema Name="erp" ... />
<Table Name="Orders" ... />

The file-system name is therefore not the source of the model object's name. It is the physical representation of that object.

XML Serialization

All project XML files use UTF-8:

<?xml version="1.0" encoding="utf-8"?>

OrmFactory uses the same XML serialization rules for both .ormfactory and .0fproj.

The serializer writes the object's Name as the first attribute on its opening tag.

For example:

<Table Name="Orders"
	Type="..." />

The exact line wrapping and indentation are serialization settings, but the XML representation itself is deterministic.

Optional Values

OrmFactory does not write every property unconditionally.

Values are omitted when they are empty or equal to their default value, depending on the property.

For example, the following column:

<Column Name="Id"
	Type="int"
	AutoIncrement="true" />

does not contain attributes for properties that have their default or empty values.

Boolean properties that are serialized only when enabled are written as lowercase true:

<Column Name="Id"
	Type="int"
	AutoIncrement="true" />

Properties that are always serialized as booleans use lowercase true or false:

<PartialGeneration WholeProject="false">

Enum values are serialized using their textual names.

XML Escaping

Attribute values and element content are XML-escaped when necessary.

For example, characters such as &, <, and > are escaped according to XML rules.

This allows names, comments, default values, generator arguments, and other text values to contain characters that would otherwise have a special meaning in XML.

Git Integration

The multi-file format is intended to work naturally with Git.

Instead of changing one large XML file when a single table is modified, a change to a table normally affects its .table file.

For example:

erp.schema/
├── Customers.table
├── Orders.table
└── Products.table

Changing Orders does not require rewriting Customers.table or Products.table.

Project resources such as connections, generators, and layouts are also stored independently.

This makes individual model changes easier to inspect and merge.

OrmFactory creates a .gitattributes file in a multi-file project:

* text eol=lf

This ensures that project text files use LF line endings in Git.

Managed and Unmanaged Files

A .0fproj directory may contain files that are not part of the OrmFactory project model.

OrmFactory does not generally treat every file in the directory as its own file.

Files that belong to the project's managed file tree are created and updated by OrmFactory. Files outside that managed tree are left untouched.

When the project is saved, OrmFactory can remove managed project files that no longer correspond to objects in the current project. Unmanaged files are not removed as a side effect of saving the project.

This allows additional files to coexist with an OrmFactory project directory.

Same Model, Different Storage

The .ormfactory and .0fproj formats represent the same project model.

For example, the following logical structure:

Project
└── Database
	└── Schema
		└── Orders

can be stored in a single file:

MyProject.ormfactory

or as:

MyProject/
└── Schemas.database/
	├── Schemas.database
	└── erp.schema/
		└── Orders.table

The physical file boundaries do not change the logical project structure.

OrmFactory can therefore load the project model independently of whether its resources were originally stored in one XML document or distributed across multiple files.