APIs cookbook

Each recipe aims for clarity, ease of use, and customizability for different use cases.

1. Setup instructions

To get started with the examples, Python is used to interact with SysON’s features and data. Python offers a powerful way to automate tasks, handle API calls, and process data, making it an ideal choice for this purpose. Follow the steps after to set up your environment and get everything ready to run the provided code snippets.

1.1. Step 1: Install required Python libraries

Confirm you have the following Python libraries installed before running the code snippets:

  • requests: For making HTTP requests to the SysML v2 API.

  • pandas: For organizing and manipulating data.

To install these libraries, run:

pip install requests pandas

1.2. Step 2: Configure SysML v2 API access

init_api.py
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.
import argparse

def init_sysmlv2_api():
    host =  "http://localhost:8080/api/rest" # Replace with your actual API host URL (1)
    return host

def parse_arguments():
    # Parse command-line arguments
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "project_id",
        type=str,
        help="The project ID.",
    )
    parser.add_argument(
        "element_id",
        type=str,
        nargs="?",  # This makes element_id optional
        help="The element ID (optional).",
    )
    return parser.parse_args()
Replace http://localhost:8080 with the actual URL of your API server if hosted elsewhere.

What this code does:

1 Define the base host: Assigns the variable host with the base URL of the SysML v2 API server.

In the examples, the SysON server uses a randomization function to generate unique IDs, so outputs can differ when you run the examples on your project.

Other code snippets use this function. To run it, see the following section about recipes.

1.3. Step 3: Test code snippets

Once you have configured the SysML v2 API access, you can start testing the recipes.

1.4. Troubleshooting

  1. Error Handling:

    • Check endpoint URLs, project_id, commit_id, and authentication tokens if the API returns errors: for example, 400 or 500 status codes.

    • Confirm the API is running.

  2. Empty Responses:

    • Verify that queried elements exist within the specified project and commit.

    • Use the SysON web interface for visual inspection.

  3. Recursive Function Depth:

    • For large models, manage recursion depth appropriately.

    • Change the logic to handle large datasets by limiting recursion depth.

2. Recipes

2.1. Project and commit recipe

Learn how to manage projects and retrieve related commits programmatically. Each recipe includes a detailed explanation, step-by-step instructions, and code snippets.

Recipes covered:

2.1.1. Get projects

This code example demonstrates how to use Python’s requests library to interact with the SysON API and retrieve a list of projects. It sends a GET request to the API endpoint for projects, processes the response, and prints the name and ID of each project.

Example script to fetch projects:

fetch_projects.py
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.

import requests (1)
from init_api import init_sysmlv2_api

def fetch_projects(host): (2)
    projects_url = f"{host}/projects" (3)
    response = requests.get(projects_url) (4)
    if response.status_code == 200: (5)
        projects = response.json()
        for project in projects:
            print(f"Project Name: {project['name']}, ID: {project['@id']}")
    else:
        print(f"Error fetching projects: {response.status_code} - {response.text}")

if __name__ == "__main__":
    host = init_sysmlv2_api()
    # Get the projects
    fetch_projects(host)

What this code does:

1 Import required libraries:
  • requests: Used for sending HTTP requests.

2 Define the fetch_projects function with one parameter:
  • host: The base API address.

3 Constructs the API endpoint address for fetching projects.
4 Sends a GET request to the API, passing the SysON address as a query parameter.
5 Handles the API response:
  • If the projects are successfully fetched - HTTP status 200, the function prints all the projects ID and name.

  • If an error occurs, the status code and error message are displayed.

Run the script:

$ python fetch_projects.py

Output:

Project Name: Batmobile, ID: 63a03bd8-a81a-4818-801a-01790ce8a086

2.1.2. Create a new project

This recipe demonstrates how to create a new project in SysON using Python. It sends a POST request to the /projects endpoint to create a new project with a unique name and description.

Example script to create a new project:

create_project.py
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.

import requests (1)
from init_api import init_sysmlv2_api
from fetch_projects import fetch_projects
from datetime import datetime

def create_project(host, project_name): (2)
    # Define project data as query parameters
    project_params = {
        "name": project_name
    }

    # API endpoint to create a project
    url = f"{host}/projects"  (3)

    # Send POST request with query parameters
    response = requests.post(url, params=project_params)  (4)

    # Check if the project creation was successful
    if response.status_code == 201:  (5)
        response_json = response.json()
        print("Project created successfully:")
        print(f"Project ID: {response_json.get("@id", "Unknown ID")}")
        print(f"Project Name: {response_json.get('name', 'Unknown Name')}")
    else:
        print(f"Error creating project: {response.status_code} - {response.text}")

if __name__ == "__main__":
    host = init_sysmlv2_api()

    # Fetch and display the list of projects currently available on the server
    print("Fetching the list of projects currently available on the server:")
    fetch_projects(host)

    # Create a new project with a unique name by appending a timestamp
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    project_name = f"New Project - {timestamp}"
    create_project(host, project_name)

    # Fetch and display the updated list of projects after creating the new project
    print("Fetching the updated list of projects after creating a new project:")
    fetch_projects(host)

What this code does:

1 Import required libraries:
  • requests: Used for sending HTTP requests.

  • datetime: Used to generate a timestamp for unique project naming.

2 Define the create_project function with two parameters:
  • host: The base API URL.

  • project_name: The name of the project to be created.

3 Constructs the API endpoint URL of project creation.
4 Sends a POST request to the API, passing the project name as a query parameter.
5 Handles the API response:
  • If the project is successfully created - HTTP status 201, the function extracts and prints the project ID and name.

  • If an error occurs, the status code and error message are displayed.

Run the script:

$ python create_project.py

Output:

Fetching the list of projects currently available on the server:
Project Name: Batmobile, ID: 63a03bd8-a81a-4818-801a-01790ce8a086
Project created successfully:
Project ID: d967b937-304f-43a9-8af6-b1f3a9d6adbe
Project Name: New Project - 2024-12-31 10:52:56
Fetching the updated list of projects after creating a new project:
Project Name: Batmobile, ID: 63a03bd8-a81a-4818-801a-01790ce8a086
Project Name: New Project - 2024-12-31 10:52:56, ID: d967b937-304f-43a9-8af6-b1f3a9d6adbe

2.1.3. Get commits

SysON always returns a single branch with a single commit.

This example extends the functionality by fetching the commit associated with a specific project ID. It constructs an address based on the host and project ID, sends a GET request, and prints the ID of the retrieved commit.

Example script to fetch commits:

fetch_commits.py
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.

import requests (1)
from init_api import parse_arguments
from init_api import init_sysmlv2_api

def fetch_commits(host, project_id):  (2)
    commits_url = f"{host}/projects/{project_id}/commits"  (3)
    response = requests.get(commits_url)  (4)
    if response.status_code == 200:  (5)
        commits = response.json()
        for commit in commits:
            print(f"Commit ID: {commit['@id']}")
        return commits
    else:
        print(f"Error fetching commits: {response.status_code} - {response.text}")
        return None

#  Retrieves the latest commit for a given project.
def get_last_commit_id(host, project_id):
    commits = fetch_commits(host, project_id)
    if commits:
        last_commit = commits[-1] if commits else None
        if last_commit:
            last_commit_id = last_commit['@id']
            print(f"Last Commit ID: {last_commit_id}")
        return last_commit_id
    else:
        print("No commits available.")
        return None

if __name__ == "__main__":
    args = parse_arguments()
    host = init_sysmlv2_api()
    project_id = args.project_id
    fetch_commits(host, project_id)

What this code does:

1 Import required libraries:
  • requests: Used for sending HTTP requests.

2 Define the fetch_commits Function with two parameters:
  • host: The base API URL.

  • project_id: The project ID.

3 Constructs the API endpoint URL for fetching commits.
4 Sends a GET request to the API, passing the SysON address and the project ID as a query parameter.
5 Handles the API response:
  • If the projects are successfully fetched - HTTP status 200, the function prints all the projects ID and name.

  • If an error occurs, the status code and error message are displayed.

Run the script:

$ python fetch_commits.py your-project-id

Output:

Commit ID: 63a03bd8-a81a-4818-801a-01790ce8a086

2.2. Element owned elements recipe

Learn how to retrieve owned elements programmatically. Each recipe includes a detailed explanation, step-by-step instructions, and sample code.

Recipes covered:

2.2.1. Get owned elements

This example demonstrates how to recursively navigate through the hierarchical structure of elements by using the SysON API. The script starts from a specific element identified by its ID and retrieves its details along with any "owned elements." The function calls itself recursively to explore all child elements in the hierarchy, printing their names, IDs, and types in an indented format to show the hierarchy visually.

Example script to get owned elements:

get_owned_element.py
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.

import requests
from init_api import parse_arguments
from init_api import init_sysmlv2_api
from fetch_commits import get_last_commit_id

# Function to fetch an element and print its name and type
def get_element(host, project_id, commit_id, element_id, indent):
     # Fetch the element in the given commit of the given project
    element_url = f"{host}/projects/{project_id}/commits/{commit_id}/elements/{element_id}"  (3)
    response = requests.get(element_url)  (1)

    if response.status_code == 200:
        element_data = response.json()
        element_name_to_print = element_data['name'] if element_data['name'] else 'N/A'
        element_id = element_data ['@id']
        element_type = element_data ['@type']
        print(f"{indent} - {element_name_to_print} (id = {element_id} , type = {element_type})") (2)
        return element_data
    else:
        return None

# Fetches immediate owned elements for a given element
def get_owned_elements_immediate(host, project_id, commit_id, element_id, indent):
    element_data = get_element(host, project_id, commit_id, element_id, indent)
    if element_data:
        owned_elements = element_data['ownedElement']
        if len(owned_elements) > 0:
            for owned_element in owned_elements:
                get_element(host, project_id, commit_id, owned_element['@id'], indent + '  ')
    else:
        print(f"Unable to fetch element with id '{element_id}' in commit '{commit_id}' of project '{project_id}'")

# Fetches owned elements recursively for a given element
def get_owned_elements(host, project_id, commit_id, element_id, indent):
    element_data = get_element(host, project_id, commit_id, element_id, indent)
    if element_data: (3)
        owned_elements = element_data['ownedElement']
        if len(owned_elements) > 0:
            for owned_element in owned_elements:
                get_owned_elements(host, project_id, commit_id, owned_element['@id'], indent+' ')
    else:
        print(f"Unable to fetch element with id '{element_id}' in commit '{commit_id}' of project '{project_id}'")  (4)

if __name__ == "__main__":
    args = parse_arguments()
    host = init_sysmlv2_api()
    project_id = args.project_id
    commit_id = get_last_commit_id(host, project_id)
    element_id = args.element_id

    #Get owned elements (immediate) for the given element in the given commit of the given project
    print("Immediate Owned Elements:")
    get_owned_elements_immediate(host, project_id, commit_id, element_id, '')

    # Get owned elements (recursive) for the given element in the given commit of the given project
    print("\nRecursive Owned Elements:")
    get_owned_elements(host, project_id, commit_id, element_id, '')

What this code does:

1 Fetches an Element: Sends a GET request to the SysON API to retrieve details about an element specified by its ID.
2 Prints Element Details: Displays the element’s name, ID, and type in a formatted, indented way.
3 Processes Owned Elements: Checks for owned elements and calls itself recursively for each one.
4 Recursive Traversal: Continues recursing through hierarchical levels until it explores and prints all owned elements.

This approach helps visualize the structure of complex models or systems, where elements are organized hierarchically. It highlights how to navigate relationships between elements efficiently by using the SysON API.

Run the script:

$ python get_owned_elements.py

Output example:

Commit ID: 63a03bd8-a81a-4818-801a-01790ce8a086
Last Commit ID: 63a03bd8-a81a-4818-801a-01790ce8a086
Immediate Owned Elements:
 - Batmobile (Definition)
   - problemStatement (ReferenceUsage)
   - systemIdea (ReferenceUsage)
   - seat (PartUsage)
   - body (PartUsage)
   - wheels (PartUsage)
   - frontLeftWheel (PartUsage)
   - frontRightWheel (PartUsage)
   - rearLeftWheel (PartUsage)
   - rearRightWheel (PartUsage)
   - battery (PartUsage)
   - batmobileEngine (PartUsage)

Recursive Owned Elements:
 - Batmobile (Definition)
  - problemStatement (ReferenceUsage)
   - N/A (LiteralString)
  - systemIdea (ReferenceUsage)
   - N/A (LiteralString)
  - seat (PartUsage)
  - body (PartUsage)
  - wheels (PartUsage)
  - frontLeftWheel (PartUsage)
  - frontRightWheel (PartUsage)
  - rearLeftWheel (PartUsage)
  - rearRightWheel (PartUsage)
  - battery (PartUsage)
   - powerPort (PortUsage)
   - capacity (AttributeUsage)
  - batmobileEngine (PartUsage)
   - enginePort (PortUsage)