πŸ“—Importer and Exporter Examples

JSON Importer Example

πŸ†• NEW IN 4.0 In this section a simple JSON document importer is implemented. The format of the JSON supported by this importer is just an example and not based on any existing format.

When the script is run through the File -> Import -> Import via Script -> Open Script… command, it will ask for a file to import and then a dialog allowing for two options: Create new document and whether Connections are predecessors or successors:

Example JSON File

{
  "groups": [
    {
      "children": [
        4,
        2,
        3
      ],
      "index": 1,
      "title": "G"
    }
  ],
  "nodes": [
    {
      "connections": [],
      "index": 2,
      "title": "E",
      "type": "Action"
    },
    {
      "connections": [],
      "index": 3,
      "title": "D",
      "type": "Action"
    },
    {
      "connections": [
        2,
        3
      ],
      "index": 4,
      "title": "C",
      "type": "Intermediate Effect"
    },
    {
      "connections": [],
      "index": 5,
      "title": "B",
      "type": "Action"
    },
    {
      "connections": [
        4,
        5
      ],
      "index": 6,
      "title": "A",
      "type": "Goal"
    }
  ]
}

The format of this JSON file allows for a list of β€œnodes” that are interpreted as entities and β€œgroups” which are interpreted as, well, groups. Only fields for titles, entity classes, edges (as β€œconnections”) and children elements of groups are parsed. It is left to an excessive to the reader to add annotations, junctors, project management data, etc.

The example file generates the following diagram:

JSON Importer Code

# import_json_example.py
# import the contents of a simple JSON file into Flying Logic
# option for having connections be to predecessors or successors
# creates entities, groups and edges, but not junctors
# Copyright 2023 Flying Logic

import json
from javax.swing import Box, BoxLayout, JLabel, JCheckBox, JComboBox

importItemLabel = "Import from JSON Example"

# importDocument: required function for an importer
# parameters
#      file: filename of the file to import
def importDocument(file):
	# make a UI using Java
	masterBox = Box(BoxLayout.Y_AXIS)

	# new document?
	controlBox = Box(BoxLayout.X_AXIS)
	newDocCheckbox = JCheckBox("Create new document")
	controlBox.add(newDocCheckbox)
	controlBox.add(Box.createHorizontalGlue())
	masterBox.add(controlBox)

	# connections meaning
	controlBox = Box(BoxLayout.X_AXIS)
	controlBox.add(JLabel("Connections are: "))
	connectionsComboBox = JComboBox(["Predecessors", "Successors"])
	controlBox.add(connectionsComboBox)
	masterBox.add(controlBox)

	# display dialog and collect options
	if 0 == Application.request("JSON Import Settings", masterBox, ("Cancel", "OK")):
		return

	# get options from user choices
	createNewDocument = newDocCheckbox.isSelected()
	connectionsAsSuccessors = (connectionsComboBox.selectedIndex == 1)
	
	# create a new doc if desired
	if createNewDocument:
		theDoc = Application.newDocument()
	else:
		theDoc = document
		
	# open and parse JSON file
	with open(file, "r") as infile:
		json_object = infile.read()
		data = json.loads(json_object)
		
		entityDict = { }
		groupDict = { }
		
		# process "nodes" as entities
		# we will create all entties and then deal with connections
		if 'nodes' in data:
			for node in data['nodes']:
				# with None parameter, no need to clear selection
				entity = theDoc.addEntityToTarget(None)[0]
				entity.title = node['title']
				entity.entityClass = theDoc.getEntityClassByName(node['type'])
				entityDict[node['index']] = (entity, node['connections'])
			
		# process "groups" as groups
		# we will create all groups and then deal with children
		if 'groups' in data:
			for node in data['groups']:
				# with None parameter, no need to clear selection
				group = theDoc.newGroup(None)[0]
				group.title = node['title']
				groupDict[node['index']] = (group, node['children'])

		# process connections
		for data in entityDict.values():
			entity = data[0]
			for connection in data[1]:
				other = entityDict[connection][0]
				if connectionsAsSuccessors:
					theDoc.connect(entity, other)
				else:
					theDoc.connect(other, entity)

		# process children, which can be an entity or group
		for data in groupDict.values():
			group = data[0]
			for index in data[1]:
				if index in entityDict:
					child = entityDict[index][0]
				else:
					child = groupDict[index][0]
				child.parent = group

Example DOT Exporter

The code below exports a document to a DOT (GraphViz) file, but with less features than the native export option in Flying Logic.

# export_dot.py
# a simple DOT format exporter, less complete then the native version in Flying Logic
# Copyright 2013 Arciem LLC

# required variable that provided the label for the item in Flying Logic export menu
exportMenuLabel = "Export Diagram to simple DOT format"

# exportDocument: required function for an exporter
# parameters
# file: filename of the file to export
def exportDocument(file):
  # open output file using Python file I/O
  fh = open(file, 'w')

  fh.write("digraph graphname {\n")
  for elem in document.all:
    if elem.isGroup or elem.isEdge:
      continue

    # use the element unique id’s (eid) to create unique id’s in DOT
    if elem.isEntity:
      fh.write("\tn" + str(elem.eid) + " [label=\"" + elem.title + "\"];\n")
    if elem.isJunctor:
      fh.write("\tn" + str(elem.eid) + " [label=\"" + elem.operator.abbreviation + "];\n")
    for outEdge in elem.outEdges:
      fh.write("\tn" + str(elem.eid) + " -> n" + str(outEdge.target.eid) + ";\n")
      fh.write("\t}\n")

  fh.close()

Last updated