How do I Merge two Archi models into one model?

Started by Bata, December 08, 2015, 18:35:04 PM

Previous topic - Next topic

Bata

Hi I would like to merge two Archi models into one model so that I can re-use my objects and their defintions without having to redo them for every model I use. Is this possible? I would very much like to know how.

Jean-Baptiste Sarrodie

Hi,

The short answer to your question is: you can't :-)

The long answer is: it may be possible if all your models are created through the exact same template (so that internal ID for elements are the same accross files) and through GRAFICO plugin. I've written a wiki topic about this use case.

There should also be some ways through the Open Group Open Exchange format and some XML merge tools but I have never tested it.

Regards,

JB
If you value and use Archi, please consider making a donation!
Ask your ArchiMate related questions to the ArchiMate Community's Discussion Board.

amicone

#2
 :) Heya, new ArchiMate user here. Yes, XML is the way to go. I haven't tried to merge two ArchiMate models in Archi, but I just merged all the artifacts from another non-standard sub-architecture with an ArchiMate architecture model through a Python script using xml.

The only issue I've noticed is that the folder organization falls apart on export/import. If you ask it to export the folder structure, it will not import it afterwards, even if you didn't change it at all.

I don't think my python script would help you much, but I can give you some pointers with some code snippets. If you aren't a python hacker, hopefully some of this will help you using your toolset, whatever that might be.

First, xpath is your friend.

Second, you want to import the elements of interest from the XML export.

For example, this snippet will get you all the business actors, here mine also has a property I added that abberviates the actor name:
import xml.etree.ElementTree as ET

ns = {'am': 'http://www.opengroup.org/xsd/archimate',
      'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}

tree = ET.parse(dataDir + "archi_export.xml")
root = tree.getroot()
ID(root)

modelOrgs = {}
for e in root.findall("./am:elements/am:element[@xsi:type='BusinessActor']", ns):
    ou = e.find("am:label",ns)
    abbr = e.find("am:properties/am:property/am:value", ns)
    modelOrgs[abbr.text] = (e.get('identifier'), ou.text)


Third, you need to manage the ID's so they are all consistent and generate new ones as needed. That's what the ID(root) call above does, it finds all the identifiers already in the XML export and stores them, so when you generate new ones there's no accidental replicated ID's (improbable, I know, but the improbable ocassionally happens). The ID.get() method here generates new ID's in the Archi format and stores them in a table so they don't get re-used:


class ID:
    ids = set()
    def __init__(self, root):
        for i in root.findall(".//*[@identifier]",ns):
            self.ids.update([i.get('identifier')])
    def getID():
         id = 'id-{:08x}'.format(random.getrandbits(32))
         while id in ID.ids:
            id = 'id-{:08x}'.format(random.getrandbits(32))
         ID.ids.update(id)
         return(id)


Fourth, you'll need a way to keep track of all the relationships, here's a sample of how I do that (don't expect to be able to follow all this, there is code that is not present here, but it should give you an idea).


relationships = []

lemRoot = root.find('./am:elements', ns)
for d in departments.keys():
    for service in departments[d].responsiblities:
        bsID = ID.getID()
        attrs = {'xsi:type' : 'BusinessService', 'identifier': bsID}
        elem  = ET.SubElement(elemRoot, 'element', attrs)
        label = ET.SubElement(elem,'label', {'xml:lang' : 'en'})
        label.text = service
        doc = ET.SubElement(elem,'documentation', {'xml:lang' : 'en'})
        doc.text = serviceDocumentation[service]
        relationships.append((ID.getID(), "AssignmentRelationship", bsID, modelOrgs[d][0]))

elemRoot = root.find('./am:relationships', ns)
for r in relationships:
    attrs = { 'identifier':r[0],
              'xsi:type':r[1],
              'source':r[2],
              'target':r[3]}
    elem = ET.SubElement(elemRoot, 'relationship', attrs)


Fifth, a python tip, you need to change the archimate xsd as the default xml namespace. Archi's XML parser kind of gets thrown for a loop if archimate isn't the default namespace.


ns = {'am': 'http://www.opengroup.org/xsd/archimate',
      'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}

ET.register_namespace('', ns['am'])
ET.register_namespace('xsi', ns['xsi']);
tree.write(dataDir + "archi_import.xml")


Hopefully, this is helpful.

Phil Beauvoir

Thanks for sharing this Python snippet! Hopefully someone will find it useful.

Phil
If you value and use Archi, please consider making a donation!
Ask your ArchiMate related questions to the ArchiMate Community's Discussion Board.