Introduction

Some people are asking how they can use some of Class Dependency Analyzer (CDA) capabilities in their own projects. Usually that means that no UI is needed. Instead the functionality of embedded CDA libraries is supposed to be programmatically.

One such functionality is the export of a dependency model to XML files. While being available via CDA UI for a long time it was hard to find out how to do it from your own code.

This short guide shows how to do that with CDA up to version 2.3.0 and for the improved API of CDA 2.4.0.

Step by Step

Following the steps below should allow exporting the dependencies of your applications to an XML file.

Prerequisite: Add the required CDA libraries to your project (see ).

  1. Create a workset that defines the archives of class files to be analyzed

  2. Initialize the workset (i.e. loading all containers and class files)

  3. Create an XML exporter with a target output file

  4. Run the export on a specific model element and its sub-elements

Required CDA Libraries

All required libraries are available in the following Maven repository: http://programmers-friend.org/maven/repo/
Most of them can also be found in https://mvnrepository.com/

Note
For the version numbers below please user either 2.3.0 or 2.4.0

Gradle dependencies

dependencies {
  compile group: 'org.pfsw', name: 'pf-cda-core', version: '2.x.0'
  compile group: 'org.pfsw', name: 'pf-cda-extensions', version: '2.x.0'
}

Maven dependencies

<dependency>
  <groupId>org.pfsw</groupId>
  <artifactId>pf-cda-core</artifactId>
  <version>2.x.0</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.pfsw</groupId>
  <artifactId>pf-cda-extensions</artifactId>
  <version>2.x.0</version>
  <scope>compile</scope>
</dependency>

Code Examples

This examples shows how to create programmatically the ODEM export of all containers and classes of MyApp.war.

CDA 2.3.0 and before

Workset workset = new Workset("export-example");
workset.addClasspathPartDefinition(new ClasspathPartDefinition("MyApp.war"));
AModelExporter exporter = new XmlFileODEMExporter();
PluginConfiguration pluginConfig = new PluginConfiguration();
pluginConfig.set(XmlFileODEMExporter.PARAM_OUTPUT_FILENAME, "/tmp/myapp-dependencies.odem");
exporter.initialize(pluginConfig);

try
{
  ModelExportEngine.instance().export(workset, null, exporter);
}
catch (Exception e)
{
  e.printStackTrace();
}

CDA 2.4.0 and later

Workset workset = new Workset("export-example", "MyApp.war");
AModelExporter exporter = XmlFileODEMExporter.forOutput("/tmp/myapp-dependencies.odem");

try
{
  ModelExportEngine.instance().export(workset, exporter);
}
catch (Exception e)
{
  e.printStackTrace();
}

Advanced

Implementing Your Own Exporter

You can also implement your own exporter by extending abstract class org.pfsw.tools.cda.plugin.export.spi.AModelExporter. That implies the extension of its superclass org.pfsw.tools.cda.xpi.AModelObjectVisitor. Just override the methods necessary to produce the output you want to create.

Tip
This approach could be used to export the object dependency model to a database.

Provide a Progress Monitor

Passing a progress monitor to the export execution can solve two purposes: . Track the elements that are processed . Abort export processing if necessary

A progress monitor just simply needs to implement interface org.pfsw.tools.cda.core.processing.IProgressMonitor.

Below is a very simple implementation of a progress monitor.

package org.pfsw.tools.cda.examples;

import org.pfsw.tools.cda.core.processing.IProgressMonitor;

public class SimpleConsoleMonitor implements IProgressMonitor
{
  @Override
  public void startProgressMonitor()
  {
    System.out.println("=== Start of workset processing ===");
  }
  @Override
  public void terminateProgressMonitor()
  {
    System.out.println("=== End of workset processing. ===");
    System.out.flush();
  }

  @Override
  public boolean showProgress(int value, Object...info)
  {
    for (Object object : info)
    {
      System.out.print("Processing: ");
      System.out.println(object);
    }
    return true; // returning false would cancel further processing
  }
}