Scripting with Groovy

Contents

Scripting with Groovy#

Introduction#

The Lattix API allows you to write Groovy scripts to extend and customize the functionality of Lattix. Groovy is a powerful dynamic language. Groovy scripts are loaded and compiled at runtime, so scripts can be quickly written and edited while Lattix is running. Groovy scripts use a Java-like syntax. Further information on how to program groovy scripts can be found here: http://groovy-lang.org/documentation.html.

Lattix will look for a directory under the install directory called “scripts-. You can also configure your own script directories by going through View–>Preference–>Scripting. All the scripts (all files with the .groovy extension) in the script directories will be compiled and loaded. A script file can contain a simple code block, and/or it can contain methods/class definitions. Each script file can produce zero or more “script actions- that will be available via the user interface (either a menu item or via the ldcscript command line program).

Specifying Actions#

Action#

A script can define “script actions- in the following ways:

  • Any block code in the script not contained in a method or class will produce a “script action- that has the same name as the script file (without the .groovy extension).

  • Any method with the name “action- will produce a “script action” that by default has the same name as the script file.

  • Any method that has the annotation @Action will produce a “script action- that by default has the same name as the script file

script1.groovy:

print("This is the Script1 script\n");

script2.groovy:

def action() {
  print("This is the Script2 script\n");
}

script3.groovy:

@Action
def sample_method() {
  print("This is the Script3 script\n");
}

multi.groovy:

@Action("Function1 Action")
def func1(){
  print("func1\n");
}
@Action("Function2 Action")
def func2() {
  print("func2\n");
}

Note: The @Action annotation can accept an optional label string for the action.

Here is an example in which the action accepts arguments. When the action is run from the Graphical User Interface, a dialog appears allowing the user to enter the values of the arguments.

params.groovy:

def action(java.io.File fileArg, Integer intArg) {
}
You can also use annotations to create labels for the arguments.
params.groovy:
@Action("Params Action")
def action(@Arg("File") java.io.File fileArg, @Arg("Number value") Integer intArg) {
}

Script Annotations#

A variety of annotations are provided to allow the user to configure where the script menu items shows up, to generate a user interface, localize for other languages, and other capabilities.

  • @Action

  • @Arg

  • @Cancelable

  • @ClassPath

  • @Description

  • @Init

  • @Keyword

  • @Localize

  • @Report

  • @RequiresVersion

  • @ScriptDescription

  • @Shortcut

@Action#

The @Action annotation defines a new action menu item.
@Action("Name of the action")

@Arg#

The @Arg annotation defines the display name of the action arguments.
@Action("Sample Action") def action(     @Arg("Partition Argument") Partition part) { ...

@Cancelable#

The @Cancelable should be specified if the action is long running and is cancelable
@Action("Sample Action") @Cancelable def action() { ...

@ClassPath#

The @ClassPath allows for jars/classes to be loaded dynamically. For best results, the @ClassPath should be specified right before the action
@ClassPath([ "\${lattix_dir}/lib/plugins/ojdbc6.jar"] ) @Action("Sample Action") def action() { ...

The following variables are understood by the @ClassPath annotation. (Note the $ needs to be escaped with a backslash, as shown in the example above)

  • ${lattix_dir} - Lattix Install directory

  • ${lattix_user_dir} - User home directory

  • ${script_dir} - directory script is located

@Description#

The @Description annotation will specify a detailed description of the action. It appears as a tooltip when you hover over the menu item.
@Action(“Sample Action”)
@Description(“Tooltip Description”)
def action()
{

@Keyword#

The @Keyword annotation will register the script using pre-defined name/value pairs.
The following example show how to assign the given action to certain profiles.
@Keyword(id=”domain”, value=”Java,.NET,C/C++,LDI”)
@Action(“Sample Action”)
def action()
{

@Localize#

The @Localize annotation
@Localize()
def en = [
“LOCALIZE_ME”: “This should be the default (english) localization”
];
@Localize(“ja”)
def ja = [
“LOCALIZE_ME”: “This should be the Japanese localization”
];
// The action name is a localization lookup
@Action(“LOCALIZE_ME”)
def action()
{

@Report#

The @Report annotation configures a custom report into Lattix. The string specified by name appears as a sub-menu item of “Custom Reports” in the Report Menu. Every report is identified by a unique id.
@Report(id=”Missing Dependencies”, name=”Find Missing Package Dependency Relationships”, group=”Custom Reports”)
def findMissingDependencies()
{

@RequiresVersion#

The @RequiresVersion annotation informs what the minimum version of Lattix that is required.
@RequiresVersion(“7.0”)
@Action(“Sample Action”)
def action()
{

@ScriptDescription#

The @ScriptDescription annotation is used for the display in the profile pane.
@ScriptDescription(“Display String for Profile Pane”)
@Action(“Sample Action”)
def action()
{

@Shortcut#

The @Shortcut annotation allows you to specify a keyboard shortcut for the action. Use the java swing syntax for the shortcut.
@Action(“Sample Action”)
@Shortcut(“ctrl A”)
def action()
{

Key Interfaces of the API#

Builtin Methods#

There are a few built-in methods that allow you to obtain certain key classes. For instance, every script needs the current ProjectModel, and it can be obtained from a builtin method.

ProjectModel model = getModel();

will allow you to access the current Lattix project. See the Java Doc API interface com.lattix.api.ProjectQuery to see other methods that are available on the “model-

ProjectSelection selection = getSelection()

will allow you to access the current selection in Architect. The selection only applies to the current view in the Lattix Project. See Java doc API com.lattix.api.ProjectSelection.

ProjectManager app = getApp();

will allow you to access application feature like opening, closing, saving projects. See Java doc API com.lattix.api.ProjectManager.

ProjectUpdater updater = getProjectUpdater()

will allow you to update the current project with new data sources. See Java doc API com.lattix.api.ProjectUpdater.

Key Classes#

Here are some of the key classes that you are likely to use most often:

  • ProjectModel

  • Partition

  • Atom

  • DependencyEdge/Dependency

  • Tag

Note that internally, Lattix is a giant data store. So, any query you make will typically be on the ProjectModel. A Partition is the subsystem that you see in the DSM or the CAD. An Atom is a domain element that is contained within a partition.

The dependencies are between atoms. A DependencyEdge identifies the source and target atoms, while a Dependency identifies only the target atom. While Dependency objects are more efficient from a memory perspective, we find DependencyEdge easier to use. In most of the scripts that we write we choose not to use the Dependency objects.

ProjectModel#

Project Model#

The interface com.lattix.api.ProjectModel represents the data store. Here are the key sections of the methods in Project Model:

Atom#

Atom#

The interface com.lattix.core.depends.Atom represents a basic domain element. Partitions contain atoms.

DependencyEdge#

DependencyEdge#

The interface com.lattix.core.depends.DependencyEdge represents a dependency between a source and a target atom. Remember that a target atom can be an external atom.

Partition#

Partition#

The interface com.lattix.core.partition.Partition represents the basic element of a Lattix project that is visible in a DSM or a CAD.

Tag#

Tag#

The interface com.lattix.core.partition.Tag represents the tag that can be applied to a partition.

Example Scripts#

To see more examples of scripts, simply look in the scripts directory of your Lattix installation.

Iterate through all Subsystems#

Iterate through all Subsystems#

/*
 * Iterates through all subsystems (aka partitions) starting at the top (root).
 */

import com.lattix.core.depends.*;
import com.lattix.core.partition.*;
import com.lattix.api.*;

@Action("Iterate through all Subsystems")
def iterate_partitions() {
    ProjectModel model = getModel();
    Partition root = model.getRootPartition();
    process(root);
}

// Recursively iterate through all partitions
void process(Partition curp) {
    println("Subsystem: " + curp.getName());
    PartitionCollection pc = model.getSubPartitions(curp);
    for (Partition p : pc) {
        process(p);
    }
}

Create New Project from Visual Studio Solution File using Clang module#

Create New Project From Solution File#

@Action("NewSolutionFileProject")
@Description("Create new project from Solution File")
def action(){

      ProjectManager manager = getApp();

      ProjectContext project = app.newProject();
      ProjectUpdater updater = project.getProjectUpdater();

      File file = new File("c:/users/default/project/app.sln");

      String dataSource = "vs-sln-file:sln_name=" + file.toString() + ",sln_cfg=Debug|x64";
      Set ds = new LinkedHashSet();
      ds.add(dataSource);

      updater.addModuleDataSources("lattix.plugin.clang", ds);

      ProjectUpdater.UpdateResult result = updater.updateProject();
}

Create Rule on selection#

@Action("CreateRule")
def createRule(){
    def model = getModel();

    def selection = getSelection(); // get currenet selection

    PartitionRelationCollection rels = selection.getSelectedRelations();
    if (rels && !rels.isEmpty()){
        PartitionRelation rel = rels.iterator().next(); // get first selection

                // create CAN-USE rule
        model.newRule(rel.getSourcePartition(), RuleType.CAN_USE, rel.getTargetPartition());

    }
}

Expand/collapse hierarchical expansion#

@Action("Expand view for selected partition")

def view_expand_demo(){
    ProjectModel model = getModel();
    def root = model.getRootPartition();

    def selection = getSelection();

    def parts = selection.getSelectedPartitions();

    if (!parts.isEmpty()){
        Partition child = parts[0];

        ProjectModelViewCollection views = model.getProjectModelViewCollection();

        ProjectModelView view = views.getView(0);
        if (view.isPartitionExpanded(child)){
                view.collapsePartitions(child);
        }else{
                view.expandPartitions(child);
        }
     }else{
        throw new Exception("no partition selected");
     }
}

Extract Metrics#

Simple example of extracting metrics#

@Action("ExtractMetrics")
@Description("Extract metric for partition")
def action(){

    def model = getModel();

    def partition = model.getRootPartition();
    def metric = model.getMetricDefinition("partition.metric.stability");
    Object value = model.getMetricValue(partition, metric);

    String metricLabel = getResourceString(metric.getName());

    out.println("partition: " + partition.getName());
    out.println("metric: " + metricLabel + " = " + value);

}

Extract To & From Dependencies and Create a Simple GUI#

Dump Dependencies for Selected Subsystem into File#

/*
 * The script puts up a graphical interface that allows a user to specify an input
 * subsystem. By default, the selected subsystem is chosen. The interface also
 * allows the user to specify a file into which the output is generated.
 */
import com.lattix.core.depends.*;
import com.lattix.core.partition.*;
import com.lattix.api.*;

@Action("Dump Dependencies for Selected Subsystem")
def dump_dependencies_to_file(@Init("selection")Partition source, File file)
{
    // Extract Project Model
    ProjectModel model = getModel();

    // Setup the writer
    PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(file)));

    // Extract all the dependencies FROM the selected partitions
    DependencyEdgeCollection edges = model.getEdges(source);
    writer.print("FROM dependency edges:");
    writer.println();

    // Loop through the dependency edges
    for (DependencyEdge edge : edges) {

         // Get the source and target of the dependency edge
         Atom sourceAtom = model.getSourceAtomFor(edge);
         Atom targetAtom = model.getTargetAtomFor(edge);

         // Write to file (tab separator for easy reading into excel spreadsheet also)
         if (targetAtom != null) {
              writer.print(sourceAtom.getDisplayName());0
              writer.print("\t");
              writer.print(targetAtom.getDisplayName());
              writer.println();
         }
    }

    // Extract all dependencies TO the selected partitions
    edges = model.getUsedByEdges(source); // Need Lattix 7.6 for this api
    writer.println();
    writer.print("TO dependency edges:");
    writer.println();

    // Loop through the dependency edges
    for (DependencyEdge edge : edges) {

         // Get the source and target of the dependency edge
         Atom sourceAtom = model.getSourceAtomFor(edge);
         Atom targetAtom = model.getTargetAtomFor(edge);

         // Write to file (tab separator for easy reading into excel spreadsheet also)
         if (targetAtom != null) {
              writer.print(sourceAtom.getDisplayName());
              writer.print("\t");
              writer.print(targetAtom.getDisplayName());
              writer.println();
         }
    }

    writer.close();
}

Custom Report: Generate File Name and Line Number of each Violation#

Custom Report to generate File Name and Line Number of each Violation#

/*
 * This custom report generates the file name and line number of
 *  violation instead of the source atom. The output consists of a table with
 *  three columns:
 *
 *    Column1- FileName : LineNumber
 *    Column2- Dependency Kind
 *    Column3- Target Atom Name
 *
 * Note: Report annotation ensures that menu item shows up under Reports
 *          instead of under Scripts
 */

@Report(id="violations_with_lines", name="ViolationsWithLineNumbers", group="Custom Reports")
def usage_report()
{
    def model = getModel();
    Query query = model.getQuery();

    // Query: "select edges.source_atom.sourcefile || ':' || edges.details.line_number as Source, edges.dependency.kind.display_name, edges.target_atom from T_VIOLATORS"

    String s1 = "edges.source_atom.sourcefile || ':' || edges.details.line_number as Source";
    String s2 = "edges.dependency.kind.display_name";
    String s3 = "edges.target_atom";

    String queryString = "select " + s1 + ", " + s2 + ", " + s3 + " from T_VIOLATORS";

    // Run the Query
    Object set = query.runQuery(queryString);

    // Generate the Report
    def theReport = getReport();
    theReport.addDefaultHeaders();
    theReport.addResultSetReport(set);
}

@Localize()
def map = [
  "ViolationsWithLineNumbers":"Violations with Line Numbers",
];

Custom Report: Uses (inherits) report with Line Numbers#

Custom Report: Uses (Inherits) report with Line Numbers#

/*
 * UsesKindsDBReportWithLines.groovy
 *
 * This custom report generates the file name and line number of Uses instead of the source atom, for the inherits dependency
 *
 * Created on May 27,2015
 *
 * Copyright (c) 2003-2015 Lattix, Inc.  All rights reserved.
 *
 */

@Report(id="uses_kinds_db_report_with_lines", name="UsesKindsDBReportWithLineNumbers", group="Custom Reports")
def usage_report(){
   def model = getModel();
   Query query = model.getQuery();

   // Create a QueryBuilder Object
   IQueryBuilder qb = query.getQueryBuilder();

 // find all the dependency kinds that represent an "inherits" relationship
   def kinds = qb.tDependencyKinds().select().cIsInherits().whereEqualTo(Boolean.TRUE).execute();

   // Create an edge query on the "edge database";
   def edgeQuery = qb.tEdgedb();

   // get reference to the linenumber
   def lineNumber = edgeQuery.cDetails().cLineNumber();

   // select the source file and linenumber
   edgeQuery.cSourceAtom().cSourcefile().select().concat(":").concat(lineNumber).selectAs("Source");

   // select the dependency kind
   def kind = edgeQuery.cDependency().cKind();
   // only include dependency kinds that are in the "kinds" set
   kind.whereIn(kinds);
   kind.select();

   // select the target Atom
   edgeQuery.cTargetAtom().select();

   // Run the query
   Results res = edgeQuery.execute();

   // get the ResultSet
   ObjectResultSet rs = res.getResultSet();

   def report = getReport();

   // add the ResultSet to the report
   report.add(rs);
}

@Localize()
def map = [
   "UsesKindsDBReportWithLineNumbers":"Expanded Uses (Inherit) Report With Line Numbers",
];

Custom Report: Uses report with Line Numbers#

Custom Report: Uses report with Line Numbers#

/*
 * UsesReportWithLines.groovy
 *
 * This custom report generates the file name and line number of Uses instead of the source atom.
 *
 * Created on May 27,2015
 *
 * Copyright (c) 2003-2015 Lattix, Inc.  All rights reserved.
 *
 */

@Report(id="uses_db_report_with_lines", name="UsesDBReportWithLineNumbers", group="Custom Reports")
def usage_report(){
   def model = getModel();
   Query query = model.getQuery();

   // Create a QueryBuilder Object
   IQueryBuilder qb = query.getQueryBuilder();

   // Create an edge query on the "edge database";
   def edgeQuery = qb.tEdgedb();

   // get reference to the linenumber
   def lineNumber = edgeQuery.cDetails().cLineNumber();

   // select the source file and linenumber
   edgeQuery.cSourceAtom().cSourcefile().select().concat(":").concat(lineNumber).selectAs("Source");

   // select the dependency kind
   edgeQuery.cDependency().cKind().select();

   // select the target Atom
   edgeQuery.cTargetAtom().select();

   // Run the query
   Results res = edgeQuery.execute();

   // get the ResultSet
   ObjectResultSet rs = res.getResultSet();

   def report = getReport();

   // add the ResultSet to the report
   report.add(rs);
}

@Localize()
def map = [
   "UsesDBReportWithLineNumbers":"Expanded Uses Report With Line Numbers",
];

Custom Metric#

/*
 * Implements a custom metric that shows the number of atoms in a subsystem.
 *
 * Copyright (c) 2003-2015 Lattix, Inc.  All rights reserved.
 *
 *
 */
@APIMetric(id = "atoms", name = "Atom Count")
def metric(Partition src, Partition target){
    def model = getModel();

    def atoms = model.getAtomsAt(src);

    if (atoms != null){
        return atoms.size();
    }
   return 0;
}

Custom Metric using partition properties#

You can create a new metric by creating a script This metric will use partition properties to retrieve the value of the metric.
This shows how the Decision Coverage metric is calculated
The @Description annotation informs Lattix how the metric will be calculated and handled:

heatmap=true

parti tionProperty=coverage.decision

warning=.8,error=.5

This will let the metric appear in the heatmap

This tells Lattix which partition property to use to calculate the metric

This gives default values that are used to calculate heatmap thresholds

@APIMetric(id = "coverage.decision", name = "DecisionCoverage", lowerIsBetter="false", aggregate="min", precision="percent" )
@Description("DecisionCoverageDesc")
@Definition(["heatmap=true", "partitionProperty=coverage.decision", "warning=.8", "error=.5"])
@HelpURL("https://cp.lattix.com/help/v12/import/coverage")
def metric3(Partition src, Partition target){
        // no implementation needed
}

@Localize("en")
def en = [
   "Decision Coverage": "Decision Coverage",
   "DecisionCoverageDesc": "Decision Coverage",
];
This metric will return “undefined” until the partition property named “coverage.decision” is set.
This API call allows you to set the named partition property like this:
model.setPartitionProperty(partition, "coverage.decision", 0.5);

Expand Members#

Expand Members#

/*
 * Expand members in the entire project
 */
@Action("Expand members")
def expand_members(){
    def model = getModel();
    Partition p = model.getRootPartition();
    model.expandMembers(p);
}

Partitioning Algorithms#

Apply one of the current Partitioning Algorithms to selected partition#

/*
 * 1. Lists the ids of all the partitioning algorithms
 * 2. Applies the component partitioner to the selected partition. If
 *    partition is selected the partitioning is applied to $root.
 *
 * The interface illustrates how to apply partitioning recursively also.
 *
 * Copyright (c) 2003-2014 Lattix, Inc.  All rights reserved.
 *
 */

@RequiresVersion("9.5")
@Action("Component Partitioning by Script")
def action(boolean recursive){
    def model = getModel();

    // Get the list of all partitioning algorithms configured.
    // The list will appear in the Lattix Message Pane.
    Iterator it = model.getOrderingAlgorithms();
    it.each {
        String id = it.getId();
        println("Partitioner id: " + id);
    }

    // Select node to apply partitioning (use root if none selected)
    Partition part = model.getRootPartition();
    def selection = getSelection();
    PartitionCollection pc = selection.getSelectedPartitions();
    if (!pc.isEmpty()) {
        part = pc.iterator().next();
    }

    // Apply the component partitioner
    DsmOrderingAlgorithm alg = model.getOrderingAlgorithm("component");
    model.performOrdering(part, alg, false, recursive);
}

Custom Partitioning Algorithms#

/*
 * Note: The use of Ordering annotation ensures that menu item shows up
 * in the list of Partitioning algorithms instead of under Scripts.
 *
 * Copyright (c) 2003-2014 Lattix, Inc.  All rights reserved.
 */

@RequiresVersion("9.5")

// --- Reverse the order of the selected partition ---
@Ordering(id="reverse_ordering.demo", name="Reverse Ordering by Script")
def action(partitions) {
    def list = new ArrayList();
    // This will reverse the order
    partitions.each {
        Partition part = it;
        list.add(0, part);
    }
    return list;
}

// --- Create a partition group for each partition ----
@Ordering(id="partitioning.demo", name="Partitioning by Script")
def action1(partitions) {
    Map map = new LinkedHashMap();
    int layer = 0;

    // this will put each partition in its own layer
    partitions.each {
        map.put(it, new Integer(layer));
        layer++;
    }
    return map;
}

class MyItem {
    Number value;
    Partition part;

    MyItem(Partition part, Number value){
        this.value= value;
        this.part = part;
    }
}

// --- Order the partitions by code size ----
@Ordering(id="ordering_size.demo", name="Code Size Order by Script")
def action2(partitions) {

    // Create a queue for sorting by value
    PriorityQueue sorted = new PriorityQueue(10, new Comparator(){
        public int compare(MyItem o1, MyItem o2){
            return o1.value.compareTo(o2.value);
        }
    });

    def model = getModel();
    String metricId = "metric.atomprop.codesize";
    //String metricId = "partition.metric.atomCount";

    // get the metric definition
    Metric metric = model.getMetricDefinition(metricId);

    // Sort the partitions by the value of the given metric
    partitions.each {
        Partition part = it;
        Number value = model.getMetricValue(part, metric);
        MyItem item = new MyItem(part, value);
        sorted.add(item);
    }

    // Create list to hold the ordered partitions
    ArrayList list = new ArrayList();

    // Get the partitions in value order, and add them to the list
    MyItem i;
    while((i = sorted.poll()) != null){
        list.add(i.part);
    }

    return list;
}

API Reference#

The API documentation is shipped with Lattix. Please see <Lattix Install Directory>/api/lattix_api_doc.zip

QueryBuilder API#

Lattix Query Language allows you to use SQL-like queries.

The queries will allow you to select objects like atoms, partitions, and edges based on specific criteria, including name, metric values and property values. The model data is represented by table-like interfaces. For instance, the IAtoms interface is used to access the atoms, while the IEdges interface is used to access the edges. The relationships among interfaces are represented by the methods on each interface.

Examples#

IQueryBuilder queryBuilder = model.getQueryBuilder();
IAtoms atoms = queryBuilder.tAtoms();
Results rs = atoms.cName().whereContains("work").select().execute();

rs.each { println("$it"); }
IQueryBuilder queryBuilder = model.getQueryBuilder();
IEdges edges = queryBuilder.tEdges();
Results rs = edges.cTargetAtom().cName().whereContains("test").select().execute();

rs.each { println("$it"); }
IQueryBuilder queryBuilder = model.getQueryBuilder();
IPartitions partitions = queryBuilder.tPartitions();
Results rs = partitions.cDisplayName().whereEndsWith(".h").select().execute();

rs.each { println("$it"); }
IQueryBuilder queryBuilder = model.getQueryBuilder();
IPartitions partitions = queryBuilder.tPartitions();
partitions.cDisplayName().whereEndsWith(".h");

partitions.cAtoms().cProperties("test").cValue().whereEqualTo(Boolean.TRUE);

Results rs = partitions.select().execute();

rs.each { println("$it"); }

IQueryBuilder#

interface IQueryBuilder {

IAtomKinds

tAtomKinds();

All of the atom kinds in the model

IPropertyDefinitions

tAtomPropertyDefinitions();

All of the atom property definitions in the model

IAtoms

tAtomdb();

All the atoms in the atom database

IAtoms

tAtoms();

All the atoms in the model

IDatasource

tDatasources();

All of the data sources in the model

IDependency

tDependencies();

All of the dependencies in the model

IDependencyKinds

tDependencyKinds();

All of the dependency kinds in the model

IPropertyDefinitions

tDependencyPropertyDefinitions();

All of the property definitionsin the model

IPartitions

tDisplayPartitions();

All of the visible partitions in the current view

IEdges

tEdgedb();

All the edges in the atomdatabase

IEdges

tEdges();

All of the visible edges in the model

IEdges

tHiddenEdges();

All of the hidden edges in the model

ICycles

tHighLevelCycles();

All of the high level cycles in the model

IProperties

tImpactSet();

ImpactSet

ICycles

tLowLevelCycles();

All of the low level cycles in the model

ICycles

tLowLevelCyclesWithMembers();

All of the low level cycles in the model, including members

IPartitions

tMainAtomPartitions();

All of the atom partitions that are defined as “main” types

IMetricDefinitions

tMetricDefinitions();

All metrics defined in the model

IModuleDefinitions

tModuleDefinitions();

The available modules

IModules

tModules();

Of the modules in the model

IPartitions

tPartitionDirectories();

**

IPartitions

tPartitions();

All the partitions in the model

IRules

tRules();

All of the rules in the model

ITags

tTags();

All of the tags in the model

IEdges

tUsedbyEdges();

All visible impact edges in the model

IPartitionRelations

tUsesPartitions();

All uses partition relations

IViolators

tViolators();

All of the violations in the model

IWorkList

tWorklist();

The worklist for the model

}

IAtomKinds#

interface IAtomKinds {

IAtomKinds

cThisColumn();

Actual row object

IStringType

cName();

Atom id

IStringType

cDisplayName();

Atom displayname

IModules

cModule();

Module that created the atom kind

IBooleanType

cIsType();

Atom kind is a type

IBooleanType

cIsMethod();

Atom kind is a method

IBooleanType

cIsField();

Atom kind is a field

IBooleanType

cIsFile();

Atom kind is a file

IBooleanType

cIsInterface();

Atom kind is an interface

}

IAtoms#

interface IAtoms {

IAtoms

cThisColumn();

Actual row object

IStringType

cName();

Name of the atom

IStringType

cDisplayName();

Display name of the atom

IAtomKinds

cKind();

Kind of the atom

IAtoms

cParent();

Parent of the atom

IAtoms

cMainParent();

Main parent of the atom

IModules

cModule();

Module that created the atom

IDatasource

cDatasource();

Container datasource for the atom

IStringType

cExternalNames();

Display external names of the atom

IPartitions

cPartition();

Partition that holds the atom

IProperties

cProperties();

Properties on the atom

IDependency

cUses();

All dependencies on the atom

IEdges

cEdges();

All edges from the atom

IEdges

cEdgesClosure();

All edges of the partition (transitive closure)

IEdges

cUsedbyEdges();

All edges to the atom (reverse edges)

IEdges

cUsedbyEdgesClosure();

All edges to the atom closure (reverse edges)

IStringType

cSourcefile();

Name of the source file if any

}

ICycleComponents#

interface ICycleComponents {

ICycleComponents

cThisColumn();

Actual row object

INumberType

cNum();

Number of items in the cycle

INumberType

cSize();

Size of the cycle

IPartitions

cCycle();

Partitions in the cycle

IPartitionRelations

cCycleRelations();

Partition Relations in the cycle

IPartitionRelations

cAllRelations();

All Partitions Relations in the cycle

}

ICycles#

interface ICycles {

ICycles

cThisColumn();

Actual row object

IPartitions

cContainer();

Container Partition

ICycleComponents

cCycles();

Partitions in the cycle

INumberType

cNumCycles();

Number of cycles

ISimpleType

cGraph();

Graph of cycles

IPartitionRelations

cBadEdges();

Bad edges

IPartitionRelations

cGoodEdges();

Good edges

IPartitionRelations

cEdges();

Edges

}

IDatasource#

interface IDatasource {

IDatasource

cThisColumn();

Actual row object

IStringType

cName();

Name of the data source

IStringType

cDisplayName();

Display name of the datasource

IModules

cModule();

Module that created the data source

IAtoms

cAtoms();

All atoms in the datasource

IProperty

cInit();

Properties of original datasource (i.e. database connection properties)

IProperty

cOptions();

Options of the data source

}

IDependency#

interface IDependency {

IDependency

cThisColumn();

Actual row object

IStringType

cName();

Dependency name

IDependencyKinds

cKind();

Dependency kind

Imodules

cModule();

Source module of the dependency

}

IDependencyKinds#

interface IDependencyKinds {

IDependencyKinds

cThisColumn();

Actual row object

IStringType

cName();

Dependency kind id

IStringType

cDisplayName();

Dependency kind displayname

IModules

cModule();

Module that created the dependency kind

IBooleanType

cIsInherits();

true if is inherits

IBooleanType

cIsInvokes();

true if is invokes

IBooleanType

cIsConstructs();

true if is constructs

IBooleanType

cIsDataRef();

true if is a data reference

IBooleanType

cIsTypeRef();

true if is a type reference

}

IEdgeDetails#

interface IEdgeDetails {

IEdgeDetails

cThisColumn();

Actual row object

INumberType

cLineNumber();

Line number

ISourceCode

cSourceCode();

Source Code

}

IEdges#

interface IEdges {

IEdges

cThisColumn();

Actual row object

IStringType

cDisplayName();

Display name

IAtoms

cSourceAtom();

Source atom of the edge

IDependency

cDependency();

Dependency object of the edge

IDependencyKinds

cKind();

Dependency kind of the edge

IAtoms

cTargetAtom();

Target atom of the edge

IAtoms

cSourceAndTargetAtom();

Source and target atoms of the edge

IBooleanType

cIsTargetExternal();

Target atom is external

INumberType

cStrength();

Strength of the edge

IProperties

cProperties();

Property of the edge

ISourceCode

cSourceCode();

Source Code

IEdgeDetails

cDetails();

Edge Details

ISourceCode

cSourceCodeRegion();

Source Code

IEdges

cWorkitems();

Work items associated with edge

}

IMetricDefinitions#

interface IMetricDefinitions {

IMetricDefinitions

cThisColumn();

Actual row object

IStringType

cName();

Metric name

IStringType

cDisplayName();

Metric display name

IStringType

cDescription();

Metric description

}

IMetrics#

interface IMetrics {

IMetrics

cThisColumn();

Actual row object

IMetricDefinitions

cDefinition();

Metric

IStringType

cName();

Metric id

IStringType

cDisplayName();

Metric display name

ISimpleType

cValue();

Metric Value

}

IModules#

interface IModules {

IModules

cThisColumn();

Actual row object

IStringType

cName();

Module id

IStringType

cDisplayName();

Module display name

IMap

cKeywords();

Module keywords

}

IPartitionRelations#

interface IPartitionRelations {

IPartitionRelations

cThisColumn();

Actual row object

IPartitions

cSource();

Source Partition of the partition edge

IPartitions

cTarget();

Target Partition of the partition edge

IEdges

cEdges();

edges

}

IPartitions#

interface IPartitions {

IPartitions

cThisColumn();

Actual row object

IStringType

cName();

Partition name

IStringType

cDisplayName();

Partition display name

IStringType

cShortDisplayName();

Partition short display name

IAtoms

cAtoms();

Atoms contained in the partition

IAtoms

cAtomdb();

Atomdatabase atoms contained in the partition

IAtoms

cMainAtom();

Main atom contained in the partition

IMetrics

cMetrics();

Metrics for the partition

IRules

cRules();

Rules on the partition

ITags

cTags();

Tags on the partition

IPartitions

cNonReferencePartition();

Return the partition that is not the reference partition

IPartitions

cParent();

Parent of the partition

IPartitions

cSiblings();

All siblings of the partition

IPartitions

cChildren();

All children of the partition

IDependency

cDependencies();

Dependencies of the partition

IDependency

cAllDependencies();

All Dependencies of the partition

IPartitions

cUsesSiblings();

All siblings used by the partition

IBooleanType

cIsRoot();

true if the partition is the root

IBooleanType

cIsReference();

true if the partition is a Reference Partition

IBooleanType

cIsOrphan();

true if the partition isorphaned

INumberType

cDepth();

The depth of the partition

IPartitions

cAncestors();

All ancestorsof the partition

IPartitions

cAncestorsInclusive();

All ancestors of the partition, including currrent partition

IPartitions

cDescendants();

All descendants of the partition

IPartitions

cDescendantsInclusive();

All descendants of the partition, including the current partition

IEdges

cUsesEdges();

All edges of the partition

IEdges

cUsedbyEdges();

All edges using the partition

IPartitions

cMainPartition();

Closest ancestor that represents container partition. (i.e. non-member partition)

IEdges

cUsesEdgesClosure();

All edges of the partition (transitive closure)

IPartitions

cPartitionImpact();

Impact of the partition

IPartitions

cMainAtomPartitionImpact();

Impact of the partition

IPartitions

cMainAtomPartitionImpactClosure();

Closure Impact of the partition

IPartitions

cImpactClosure();

Closure Impact of the partition

IPartitions

cUsesPartitions();

Partitions used by this partition

IPartitions

cMainUsesPartitions();

Partitions used by this partition

IPartitionRelations

cRelationPartitions();

Parent of the partition

}

IProperties#

interface IProperties {

IProperties

cThisColumn();

Actual row object

IPropertyDefinitions

cDefinition();

Property Definition

IStringType

cName();

Property name

IStringType

cDisplayName();

Property display name

ISimpleType

cValue();

Property Value

}

IPropertyDefinitions#

interface IPropertyDefinitions {

IPropertyDefinitions

cThisColumn();

Actual row object

IStringType

cName();

Definition name

IStringType

cDisplayName();

Definition display name

IStringType

cType();

Type, true

IModules

cModule();

Module

}

IRules#

interface IRules {

IRules

cThisColumn();

Actual row object

IStringType

cName();

Name of the rule

IStringType

cRule();

Rule title

IStringType

cSource();

Source of the rule

IStringType

cTarget();

Target of the rule

IBooleanType

cIsDefault();

true if this is the default rule

}

ITags#

interface ITags {

ITags

cThisColumn();

Actual row object

IStringType

cName();

Tag name

IStringType

cColor();

Tag color

IPartitions

cPartitions();

Partitions directly in the tag

IEdges

cEdges();

Edges in the tag

ITags

cSubtags();

Sub tags

IPartitions

cAllPartitions();

All Partitions (resolves children) in the tag

}

IViolators#

interface IViolators {

IViolators

cThisColumn();

Actual row object

IAtoms

cSourceAtom();

Source atom of the violation

IRules

cRule();

Rule that caused the violation

IPartitions

cPartition();

Source partition of the violation

IDependency

cDependencies();

Dependencies that caused the violation

IEdges

cEdges();

Edges that caused the violation

IEdges

cEdgedb();

Edges (from Edge Database) that caused the violation

}

IWorkList#

interface IWorkList {

IWorkList

cThisColumn();

Actual row object

IStringType

cName();

Work item name

IStringType

cDisplayName();

Work item title

IStringType

cDescription();

Work item description

IWorkList

cParentWorkItem();

Parent work items

IWorkList

cSubItems();

Subwork items

IWorkItemData

cData();

Data in the work item

IWorkItemData

cNamedData();

Data in the work item

}

Select#

interface Select {

Object

concat(Object param0);

Object

function(String param0, Object[] param1);

Object

groupBy();

Object

orderBy(boolean param0);

Object

select();

Object

forall(Object param0, Object[] param1);

Object

foreach(Object param0, Object[] param1);

Object

selectAs(String param0);

}

Table#

interface Table extends Select, Where {

Object

concat(Object param0);

Object

function(String param0, Object[] param1);

Object

select();

Object

groupBy();

Object

orderBy(boolean param0);

Object

forall(Object param0, Object[] param1);

Object

foreach(Object param0, Object[] param1);

Object

selectAs(String param0);

Results

execute();

Results

execute(String param0, Object[] param1);

SubQuery

subQueryLink(String param0, Object[] param1);

Class

getTableClass();

}

Where#

interface Where {

Table

whereLike(String param0);

Table

whereContains(Stringparam0);

Table

whereLessThan(Objectparam0);

Table

whereNotNull();

Table

whereNull();

Table

whereOr();

Table

whereEndsWith(Stringparam0);

Table

whereAnd();

Table

whereEqualTo(Object param0);

Table

whereIn(Object param0);

Table

whereNotIn(Object param0);

Table

whereGreaterThan(Objectparam0);

Table

whereStartsWith(Stringparam0);

Table

whereNotEqualTo(Objectparam0);

Table

whereOpenParen();

Table

whereLessThanOrEqualTo(Objectparam0);

Table

whereCloseParen();

Table

whereGreaterThanOrEqualTo(Objectparam0);

}

Script Editor Tool#

Lattix Provides a groovy script editing tool that works with the Lattix environment. Please contact support@code-clinic.com to get a copy of the Lattix Script Editor for Windows or Linux

Before You Start#

The script editor is based on eclipse and requires Java. You will need to have Java 1.8 installed.

On Windows: unless you are Administrator on your computer, you will not be able to edit the scripts that are installed in c:/Program Files with Lattix Architect.

You can add your own script directories that will allow you to edit your scripts. You can add your own script directories from Lattix Architect via the menu View->Preferences. Then select “Scripting” on the left.

image0

Note: Before you run the Script Editor, close Lattix Architect. (You will be able to launch Lattix Architect from the script editor if you wish to debug the script)

Setting Up Editor#

To run the script editor, simply run the executable “script_editor.exe”
After the GUI starts up, you will need to specify the location of the Lattix Installation.
  • Select the Menu Windows->Preferences.

  • In the Preferences Dialog, select “Lattix Preferences” lattix_script_editor_prefs_dialog

  • Turn on “Use External Lattix Install”

  • Enter the location of the Lattix Install in the first text box

  • The second text box is the name of your Lattix user properties file

  • Click OK. (You may need to close GUI and reopen)

image1

Debugging Scripts#

Open the script you want to debug by doubling clicking on it in the Script Navigator.

  • If there are no scripts in the navigator, double check that you have the correct Lattix Install directory specified. Also try clicking the “Refresh” button

  • When the script opens, you will see errors int he script. These are due to a bug in the groovy plugin that is preventing groovy “aliases” from being recognized in the editor

image2

To start debugging, launch Lattix Architect by clicking the “Debug Lattix” button.

  • If you see an “Errors in workspace” dialog, you can ignore it by checking the “Always launch without asking” checkbox and clicking the “Proceed” button

  • If Architect does not launch, try closing and restarting the Script Editor

image3

You can add breakpoints in the script by doubling clicking to the left of the line of code you wish to stop on

You should be able to edit the script while debugging, however, if you change the script you will need to open the “Scripts” menu in Lattix to force the script to be recompiled.

Troubleshooting#

If you get an error on startup, it may be using the wrong version of java.
You may need to edit the file “script_editor.ini” to force using Java 8
-startup
plugins/org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.200.v20150204-1316
-data
@noDefault
-vm
c:\jdk1.8.0_161\jre\bin\javaw.exe
-vmargs
-XX:MaxPermSize=128M
-Xmx999m