Home / Blog / Migration & Interoperability

Folder Structures, Specializations and the Metadata Most Tools Throw Away

Nobody notices an import wizard losing data on the day it happens. The elements are there, the relationships look right, the diagram renders. It's three months later, when someone opens the client's original Sparx repository to check something and finds a folder structure, a stereotype, or a diagram convention that never made it across, that the loss becomes visible — and by then nobody remembers exactly what else quietly didn't survive the trip.

This is the normal failure mode of architecture tool interoperability, not the exceptional one. Every import wizard has to translate a foreign file into its own internal metamodel, and every metamodel is narrower than the union of everything every source tool can express. Faced with a concept it doesn't have a slot for, the overwhelmingly common behavior is to drop it silently rather than fail loudly. The import reports success. The elements show up. Nothing in the user interface says "by the way, four things about this model didn't come across," because from the tool's point of view, nothing went wrong — it imported everything it knows how to represent. The gap is invisible by construction.

What an import wizard is actually optimizing for

It helps to be precise about what an import wizard is built to do, because the answer explains the failure mode instead of just describing it. An import wizard maps a source format onto a target metamodel: this XMI element becomes that internal object, this attribute becomes that field, this relationship type becomes that edge. Anything in the source file that has no corresponding concept in the target metamodel isn't rejected or flagged — it's simply never read into anything, because there was never a mapping rule written for it in the first place. The wizard's test for success is "did every element the target metamodel understands get created correctly," not "did everything in the source file arrive somewhere." Those are different bars, and most tools are built, tested, and demoed against the first one.

This is a reasonable design choice in isolation — a tool can't build first-class support for every stereotype, tagged value, and layout convention that every EA practice in the world has invented over twenty years of Sparx and Archi usage. The problem isn't that tools have a narrower metamodel than the sum of everything out there; every tool does, necessarily. The problem is what happens to the data that falls outside that metamodel. Silently discarding it and silently preserving it verbatim look identical in the import wizard's success dialog. They look very different three months later.

The tell: an import wizard that reports success cannot, by itself, tell you whether it imported everything or imported everything it knows how to represent. Those are different claims, and the wizard only ever makes the second one.

Four places metadata quietly dies

Some categories of loss are more common than others, and they're worth walking through individually, because each one is invisible for a slightly different reason and each one costs a different person time when it finally surfaces.

Folder and package hierarchy that encoded organizational meaning

A Sparx EA repository or an Archi model that's been lived in for a while organizes its contents into a package or folder tree, and in a mature practice that tree is rarely arbitrary. "Applications by business domain," "grouped by the review board that owns them," "split by which regulatory framework applies" — these are structural decisions a client's EA team made deliberately, sometimes years before anyone currently on the project was involved, and they carry real information: which folder something sits in can answer "who's accountable for this" or "which governance process does this fall under" faster than any property field would, because the client already built their working habits around navigating by that tree.

A canonical model built around a flat list of elements, or one that supports only a single level of grouping, has no natural place to put a five-level nested package hierarchy. The path of least resistance for an importer is to flatten it — either everything lands in one default location, or the hierarchy collapses to whatever shallow grouping the target tool happens to support. The elements themselves are all present and correctly typed, which is exactly why nobody notices immediately: the loss is structural, not content-level, and structural loss doesn't show up when you're checking that individual elements imported correctly.

Stereotypes and specializations that carried real semantic information

Sparx EA and Archi both let a modeler attach a stereotype or a specialization on top of a base type — an Application Component tagged «Legacy», an ArchiMate Application Service specialized as «RegulatedService», a UML class carrying a custom stereotype that a client's tooling checks for during a governance review. These aren't decorative labels. They're often the actual mechanism by which a client's EA practice distinguishes categories of thing that matter to them but that no generic metamodel would ever anticipate — "this one needs sign-off from Legal before it can be retired," encoded as a specialization rather than spelled out anywhere else.

An importer that only understands the base ArchiMate or UML type maps everything down to that type and, in the common case, has nowhere to record what the stereotype originally was. What comes out the other side is semantically thinner than what went in: an Application Service where there used to be a «RegulatedService». Nothing about the import looks wrong, because an Application Service is a perfectly valid thing for that element to be — it's just not the whole truth about it anymore, and the missing half is exactly the half a compliance reviewer six months later is going to go looking for.

Diagram styling that reflected a deliberate visual convention

Color, line style, and z-order on a diagram look cosmetic, and sometimes they are. But plenty of EA practices build real conventions on top of them: red border means high risk, dashed outline means planned-but-not-live, a particular fill color marks anything outsourced to a third party. These conventions are usually undocumented anywhere except the diagram itself and the memory of whoever set them up — which makes them exactly the kind of thing that looks safe to discard, because no field anywhere says "this fill color is meaningful," and exactly the kind of thing that causes real confusion when it's gone, because the next person to open the diagram loses a signal they didn't know they were relying on.

Z-order is a quieter version of the same problem. When two elements deliberately overlap on a diagram — a security boundary drawn behind the components it contains, say — which one renders on top depends on stacking order, not just position. An importer that captures x/y coordinates but not z-order can reproduce a diagram that looks almost right and reads completely differently, because the boundary now sits in front of the components instead of behind them.

UML-level detail on native EA classes

Sparx EA supports full UML class modeling underneath its architecture views — actual attributes with types and visibility, operations with parameter lists and return types, on classes that also happen to be part of an architecture model. A client that's used EA for both application architecture and detailed data or interface design has real UML content sitting on elements that an ArchiMate-flavored or C4-flavored import path has no concept for at all, because neither ArchiMate nor C4 has a native notion of a class operation with typed parameters.

This is the case where the mismatch is most obvious in hindsight and most easily missed in practice, because the element itself — the class — imports just fine as an application component or a data object. It's only the detail hanging off it that has nowhere to go. Someone eventually needs the exact signature of an operation that was modeled in EA specifically so an integration team wouldn't have to go read the source code to find it, and discovers that the architecture tool they moved to for faster diagramming and AI-assisted editing kept the box but ate the contents.

A shorter version of the same pattern shows up in a few other places worth naming, because they're common enough to matter even though they're smaller individually: the and/or setting on an ArchiMate junction, which changes what the junction actually means and not just how it looks; and tagged values attached at the root of an element rather than nested under a specific property, which some tools treat as a first-class concept and others don't recognize as anything at all.

A typical import wizard keeps what maps to its own metamodel and drops the rest, versus one that keeps everything by sealing the unmapped part in an extensions bag Sparx EA class stereotype, folder, operations/params, diagram color + z-order Typical import keeps name + base type discards the rest Generic class looks fine, thinner Round-trip envelope semantic core (editable) extensions bag sealed, verbatim tied to originating system Sparx EA class same stereotype same folder same operations same diagram styling
Two imports of the same EA class. One keeps only what maps to a generic metamodel. The other keeps everything, editable core plus a sealed bag of what it doesn't display, and reconstructs the original on export.

Why the discovery always comes months later

The gap between losing data and noticing it is rarely short, and the reason is structural, not carelessness on anyone's part. Most of the categories above aren't things anyone checks for on day one. A newly imported model gets reviewed for the things people actually look at right after a migration: are the applications there, do the main relationships look right, does the primary diagram render sensibly. Folder structure, stereotype fidelity, operation signatures, and diagram color conventions aren't on that checklist, because nobody thinks to check for the absence of something until they specifically need it.

The need usually shows up sideways. A compliance review asks which systems are tagged as regulated, and the answer used to be a filter on a stereotype that no longer exists in the tool doing the reviewing. An integration developer needs the exact parameter list an EA class operation carried, because it was the only place that detail was ever written down, and finds a data object with a name and nothing else. A client opens a diagram expecting the risk color-coding they've used for years and finds every box the same neutral fill. None of these are edge cases invented for a blog post — they're the ordinary, predictable consequence of an import step that treated "doesn't fit my metamodel" as equivalent to "doesn't matter."

By the time any of this surfaces, the person who ran the original import is often not the person diagnosing why the data is gone, and the original source file may have already been overwritten by further work in the new tool — which is what makes the loss expensive rather than merely annoying. A one-time export mistake caught immediately is a five-minute fix. The same mistake discovered three months and several rounds of edits later is a much harder question: was the missing stereotype ever there, and if it was, is the only copy of it now the client's original EA backup from before the migration started.

The round-trip envelope pattern

The fix isn't to keep widening the canonical model's own vocabulary until it eventually understands every stereotype, folder convention, and diagram color scheme every EA practice has ever invented. That's an unwinnable arms race, and chasing it produces a bloated, tool-specific metamodel that stops being genuinely portable across ArchiMate, C4, and plain generic modeling — which defeats the actual point of having a profile-driven canonical model in the first place.

The fix is to stop requiring every piece of imported data to earn a place in the canonical model's own vocabulary before it's allowed to survive. Split what comes in on import into two parts. The first part is whatever maps cleanly onto the canonical model's own concepts — name, base type, relationships, the properties the tool actually understands and lets you query, edit, and validate. That part becomes a genuine, first-class member of the model: editable on the canvas, reachable by an AI-proposed patch, checked by rules. The second part is everything that doesn't map — the stereotype the base type doesn't capture, the folder path, the diagram's fill and z-order, the UML operation signatures, the junction's and/or setting, the root-level tagged values — and that part gets stored verbatim in a reserved extension area attached to the element, tied to the system it came from, without the canonical model needing to interpret a single byte of it.

This is the pattern Mooodels applies on import from Archi and Sparx EA. An element that arrives with a custom stereotype, a five-level folder path, UML operations with typed parameters, and a specific diagram fill color doesn't lose any of that on the way in — the parts the model actively works with become real, editable content, and everything else rides along in an extensions bag scoped to the system that produced it. Nothing about that bag is displayed by default, and nothing about it is required for the element to be useful inside Mooodels: you can rename it, reconnect it, run linting against it, apply an AI-proposed change to it, exactly as if the extension data weren't there at all. The difference only becomes visible on export, when the bag comes back out attached to the same element it arrived on, and the folder, the stereotype, the operation list, and the styling are exactly what they were.

Element
├── core                 (name, type, relationships — editable, queryable)
├── properties           (tags/attributes the profile understands)
└── extensions
    └── sparx-ea         (tied to originating system)
        ├── stereotype       "RegulatedService"
        ├── folderPath       "Domains/Finance/Regulated"
        ├── operations       [{ name, params, returnType }, ...]
        └── diagramStyle     { fill, line, font, zOrder }

The naming matters: the extension bag is explicitly scoped to the system it came from, rather than dumped into one undifferentiated bucket. An element imported from Sparx and one imported from Archi can each carry extensions with a different shape, because they're different source systems with different concepts to preserve — a Sparx-origin element's bag might carry UML operations and a folder GUID, while an Archi-origin element's bag carries a specialization name and a folder reference specific to Archi's own model. Keeping them separated by origin is what makes export correct: on the way out, the tool reconstructs the target format using the extension data that actually belongs to that format, not a generic pile of metadata that happens to look similar across tools but isn't interchangeable between them.

What's at riskWhere it normally livesWhere Mooodels keeps itOn export
Folder/package hierarchySparx package tree, Archi folder treeextensions.folderPath, per originating systemReconstructed in the same nested structure
Stereotype / specializationEA stereotype field, Archi specialization nameextensions.stereotype alongside the mapped base typeReapplied on top of the same base type
Diagram stylingFill, line, font color; z-order per elementextensions.diagramStyle per view membershipReproduced on the same view, same stacking order
UML attributes/operationsNative EA class detail — params, return types, visibilityextensions.operations / extensions.attributesRewritten as native EA class members
Junction and/or typeArchiMate junction semanticsextensions.junctionTypePreserved, not defaulted to "and"
Root-level tagged valuesEA/Archi tagged value pairs outside the mapped property setextensions.taggedValues, raw key/value listReattached at the same element level

What this deliberately doesn't try to do

It's worth being honest about the limits of the pattern, because overclaiming it is its own kind of dishonesty. An extension bag preserves data faithfully; it doesn't make that data useful inside the tool that's carrying it. Mooodels won't let you query, filter, or run a rule against a stereotype that only exists inside a Sparx extension bag, in the same way it can against a property that's actually part of the canonical model's own schema — because doing that would mean the tool has to understand what the stereotype means, which is exactly the scope-creep problem the envelope pattern exists to avoid. The bag guarantees the data isn't lost. It doesn't promise the data is first-class inside the new tool, and pretending otherwise would be a different kind of misleading claim than the one this whole approach is trying to fix.

The honest framing is that the extension bag buys time and safety, not feature parity. A client's regulated-system stereotype survives the trip through Mooodels and comes back out intact whether it was ever touched inside the tool or not. If that stereotype needs to become something Mooodels can actually reason about — filter on, validate with a rule, show as a colored badge on a view — that's a deliberate modeling decision to promote it out of the extension bag and into the profile's own property set, and it's a decision worth making only for the handful of things that actually need to be queried, not for everything that happened to arrive in the bag.

There's a second limit worth naming: an extension bag only helps with data that survives the import step in some form. If a source tool's own export already dropped something before Mooodels ever saw the file — some EA add-ins mangle their own data on export in ways no downstream tool can recover — no envelope pattern on the receiving end fixes that. The pattern protects against the receiving tool being the one that throws things away. It can't undo damage done upstream of it.

What to check before trusting an import

A few concrete checks tend to surface whether a tool is genuinely preserving what it imports, or just mapping what fits and quietly dropping the rest:

The underlying test is the same one that matters for any serious interoperability claim: does the tool's success message mean "everything came across," or does it mean "everything I know how to represent came across"? Most import wizards, including good ones, are quietly making the second claim while sounding like they're making the first. A tool built around a round-trip envelope is one of the few that can actually make the first claim and mean it — not because it understands more of your client's metamodel than anyone else does, but because it stopped requiring understanding as the price of preservation.

See the model this article describes, working in a real editor.

Try the live demo