🏁Getting Started

Flying Logic implements a powerful internal scripting language. Scripts can be used to create or manipulate documents and change Flying Logic’s application preferences. In addition, document importers and exporters can be written as scripts, including document transformation through Extensible Stylesheet Language Transformations (XSLT).

API Version

API 1.14

This edition of the Scripting Guide describes the Flying Logic Scripting API version 1.14. This is the API contained within Flying Logic 4.0.

Scripting with Python

Flying Logic scripts are written in the Python™ programming language. This guide does not provide an extensive tutorial on Python, but only a quick overview for simple understanding of writing scripts. Online sources for information on Python or the specific implementation Flying Logic uses called Jython (Python for the Java Platform) can be found in Online Resources.

Python is an interpreted object-oriented program language. Small programs (called scripts) can be written and executed by Flying Logic via the Run Script, Import Via Script and Export Via Script menu items.

Simple scripts can be written without a knowledge of object-oriented programming, but complex scripts can benefit from such knowledge. Most of the variables that Flying Logic provided to scripts are objects, but can be manipulated fairly easily.

Here is a very simple script:

Application.alert("Hello, world!")

If you type the line above into a text file named hello.py and then select that file via the Run Script menu item, a dialog will appear with the message “Hello, world!” The .py part of the file name is the standard file extension for Python scripts.

Every Python script run via Flying Logic is provided a number of predefined variables. One of those is the Application object, which provides access to various features of the application that are not document-specific. The alert method of Application displays the string of text provided as a parameter to the method.

A second variable provided to all scripts is the document object. Here is a simple example of using this object:

Application.alert( document.title )

Create a script with the above line. In Flying Logic create a new document, open the Document Inspector and enter a value into the Title field. Use the Run Script command to execute the new script. A dialog should open with the “message” being the title you entered.

The document object gives you access to everything in the “current document”; i.e., the document that was active when you ran the script. The title instance variable of this document object gives access to the title field of the Document Inspector.

Many variables in the document (and Application) object can be read and written. If you run a script with the following line:

document.title = “A Simple Script Example”

you will find that the title field of the document has been changed.

Here is one more simple example that also demonstrates how to create conditional expressions, loops and blocks in Python and shows how to use the output console. Create a script with the following lines:

for ge in document.selection:
  if ge.isEntity:
    print ge.title
print "Done"

Python does not indicate the end of a statement with a semicolon or other delimiter like many other languages. Instead a newline indicates the end of a statement. The print element.title line is statement.

There are two looping statements in Python. The for loop executes a block once for each element in a sequence. A block in Python is indicated by indentation. The lines if ge.isEntity: and print ge.title are inside the for block, while print "Done" is not. The colon at the end of the for statement indicates the start of a block.

The selection variable of document returns a sequence containing objects representing all the selected graph elements in the document. The each loop of for block, the local variable ge is assigned one of the elements of selection.

The first line in the for block is a conditional if statement. If the condition is true, the conditional block is executed. The line print ge.title is inside the if statement’s block. (This also makes it a nested block.) If the variable isEntity of the ge object is true, then the title of the ge object (which must represent and entity in Flying Logic) will be printed.

You may be wondering where the print function prints text (or strings as they are called in Python). By default strings are printed to Flying Logic’s scripting console, which is a window that will open to display printed strings. This console will also appear when an exception occurs in the script and an error message is printed.

In summary, the above script prints the title of all selected entities to the console and then the string “Done”.

The Application and Document objects have many variables and methods that can be used to perform virtually every command in Flying Logic. The document object is an instance of the Document class. A script can retrieve objects representing other open documents other that the “current document” or even open or create new documents via the Application object. The Application object is a singleton: it is an instance of the Application class, but there is only ever one instance of that class. A complete class reference can be found in Predefined Variables and Classes.

About Jython and Java

Flying Logic uses the 2.7.0 version of Jython, which is compatible with the 2.7 command-line version of Python; i.e., CPython. Scripts have access to all features of a vanilla installation of Jython.

Scripts also have access to common Java modules that are distributed with Java SE Release 15 including java.base, java.datatransfer, java.desktop, java.management, java.prefs, java.sql, java.xml, and jdk.charsets Builds of Flying Logic on some platforms may have access to additional modules.

Example JSON Importer has an example of directly accessing Java to implement dialogs for an importer.

Don't call exit()!

Calling sys.exit() in a script will actually terminate Flying Logic. Unless that is your desired result, avoid calling this function to exit a script!

Writing Importers and Exporters

Flying Logic document importers and exporters can be written in Python. The same pre-defined classes and variables exist for a regular script, but there are special functions and variables that a script must define to function as an importer or exporter.

An importer must define the function:

def importDocument(filename):
  """ code here """

This function is called to import the file with the given filename. If you are importing into the current document, you can use the pre-defined global variable document. To instead create a new document, call the method newDocument() in the Application object.

An importer must also define a global variable with the identifier importItemLabel. This is used to determine the label for the menu item that will be assigned to the importer script. For example:

importItemLabel = "Import Diagram from CSV File"

An exporter must define the function

def exportDocument(filename):
  """ code here """

and a global variable with the identifier exportItemLabel.

exportItemLabel = "Export Diagram to CSV File"

For an exporter you will normally be working the existing document object.

You can open, read and write files by using either the Python file functions supported by Jython or the standard file classes in Java SE.

For completeness, other scripts started by selecting the Run Script... menu item can be given a custom item name by assigning a string to runItemLabel.

XSLT Importers and Exporters

Flying Logic’s Python interface can also be used to create importers and exporters that perform their functionality via Extensible Stylesheet Language Transformations (XSLT). XSLT is a language for transforming XML documents into other XML documents. The transformation is encoded in an XSLT input document, which is itself an XML document. These XSLT input documents can either be separate files or embedded in a Python script.

Since Flying Logic documents are in XML format, XSLT can be used to transform other document formats to and from Flying Logic. Performing this transformation does require that a XSLT input document author know the schema of the XML in a Flying Logic document. Instructions for downloading the complete XML Schema Definition (XSD) for Flying Logic documents can be found in Flying Logic Document Format, followed by additional information on how to interpret the schema.

Here is a short example of how to import a document using a string as the XSLT document:

xslt_string = """ some XSLT document as embedded string """
def importDocument(filename):
  Application.importDocument( filename, (Application.XSLT_STRING, xslt_string) )

More detailed example of an importer and exporter can be found in Importer and Exporter Examples.

Using Third-Party Python and Java Libraries

It is possible to access third-party Python and Java libraries from a script using the standard import feature of Python. To facilitate this, the global variable scriptParentDirectory is initialized with the path to the script’s location in the filesystem. A script can then be bundled with additional resources it requires, including libraries and other assets.

Use of a third-party Python library requires adding the path to the library to the Python import search path. This requires appending the library’s directory to sys.path.

import sys
sys.path.append(scriptParentDirectory)
import some_python_package

Use of a third-party Java library requires calling the Application method appendClassPath. The parameter to this method should be a list of either directories containing Java class files or paths to jar files.

Application.appendClassPath( [scriptParentDirectory + "SomeJavaLibrary.jar"] )
import some_java_package

Using third-party JDBC libraries to access databases requires the use of one of two special methods found in the Application class: createCompatibleDriver or createSQLConnection. See those methods for examples of usage.

Scripting Console

The print function in Python outputs a string to standard output. A Python program running in Flying Logic has its standard out redirected to the Scripting Console window. This window will appear whenever the print function is used.

A multi-line text area shows every string printed. For example the text area above shows the result of the statement

print "The author of current document:", document.author

assuming the author field in the Document inspector has been set to “Wolf”.

The text persists between execution of different scripts. Select the Clear Console button to erase the text. Select the Save Console button to save the text to a file.

If the Scripting Console is closed or hidden behind other windows, it can be made to appear by selecting the Show Console menu item.

Functionality Changes While Running a Script

There are some changes to Flying Logic’s functionality while a script is running.

  • Layout of changes to a graph are deferred until the script completes.

  • Auto-editing of new entity titles is disabled.

  • All changes to a document are coalesced into one undo action (but see the beginCoalesceUndo method of Document for how to control this feature.)

  • Calculations of confidence values and project management dates are by default deferred until the script ends or endCoalesceUndo is called. If you need these calculations to occur mid-script, call the new document method operateAll. This method can be slow, so only call when absolutely necessary.

Exception Handling

Some scripting methods can return a Java exception instead of a Python exception. To handle these Java exceptions, you can import the class java.lang.Exception and then catch them.

from java.lang import Exception
# assume you have variables referencing an edge and a group
try:
  document.modifyAttribute([anEdge], "parent", anGroup)
catch Exception, e:
  print e.message

Alternately, you can import other Java exception classes if you want to handle exceptions caused by calling Java library code directly.

Uncaught exceptions will be printed to the Scripting Console. This includes uncaught Java exceptions, which prevents the Flying Logic’s normal exception report dialog from being displayed.

Last updated