Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
5ab080e
Java modernization: collections, lambdas, try-with-resources, depreca…
rostam Mar 15, 2026
8620959
Java modernization continued: StringBuilder, try-with-resources, isEm…
rostam Mar 15, 2026
b534cd0
Modernize visualization, select, and animator classes
rostam Mar 15, 2026
12891f6
Replace Iterator while-loops and StringTokenizer with modern idioms
rostam Mar 15, 2026
f0d0a8f
Replace StringBuffer, Stack with modern equivalents
rostam Mar 15, 2026
631e0c8
Replace e.printStackTrace() with ExceptionHandler.catchException() th…
rostam Mar 15, 2026
bf29656
Convert Vector to List/ArrayList in extension algorithms and utilities
rostam Mar 15, 2026
b0f9ee4
Convert remaining Vector usages to List/ArrayList
rostam Mar 15, 2026
b559350
Convert Iterator while-loops to for-each in algorithm and UI files
rostam Mar 15, 2026
8a832a7
Convert remaining Iterator while-loops to for-each
rostam Mar 15, 2026
51c2928
Fix deprecated Double(double) constructor usage
rostam Mar 15, 2026
0256645
Modernize codebase: dead code removal, tests, try-with-resources, deb…
rostam Mar 15, 2026
0d13ef1
Remove all Vector usages, debug prints, and fix string concat in loops
rostam Mar 15, 2026
1bc54f5
Add Checkstyle enforcement and expand test coverage
rostam Mar 16, 2026
982396c
Fix four bugs reported in GitHub issues
rostam Mar 16, 2026
0b8fee6
Reference GitHub issues fixed in this branch
rostam Mar 16, 2026
d8255a0
Fix ReportsTest: remove placeholder assertions, fix two wrong expecte…
rostam Mar 16, 2026
5579956
Add test execution to GitHub Actions CI
rostam Mar 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
29 changes: 22 additions & 7 deletions .github/workflows/ant.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
name: Java CI

on: [push]
on: [push, pull_request]

jobs:
build:
build-and-test:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1
- name: Set up JDK 1.8
uses: actions/setup-java@v1
- uses: actions/checkout@v4

- name: Set up JDK 11
uses: actions/setup-java@v4
with:
java-version: 1.8
java-version: '11'
distribution: 'temurin'

- name: Download JUnit 5 dependencies
run: |
mvn dependency:get -q -Dartifact=org.junit.jupiter:junit-jupiter-api:5.9.3
mvn dependency:get -q -Dartifact=org.junit.jupiter:junit-jupiter-engine:5.9.3
mvn dependency:get -q -Dartifact=org.junit.platform:junit-platform-engine:1.9.3
mvn dependency:get -q -Dartifact=org.junit.platform:junit-platform-commons:1.9.3
mvn dependency:get -q -Dartifact=org.junit.platform:junit-platform-launcher:1.9.3
mvn dependency:get -q -Dartifact=org.opentest4j:opentest4j:1.2.0

- name: Build with Ant
run: ant -noinput -buildfile build.xml
run: ant -noinput

- name: Run tests
run: ant -noinput test
105 changes: 105 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Build & Run

```bash
# Full clean build + run (with JDWP debug port 8000)
./make.sh

# Build only
ant clean && ant

# Run the built JAR
java -jar binary/graphtea-main.jar

# Platform-specific launchers
./GraphTea-linux.sh
./GraphTea-mac.sh
./GraphTea-windows.bat

# Create distribution packages (macOS .dmg, Windows .exe, Linux .deb)
./create_packages.sh
```

Build output goes to `build/` (compiled classes) and `binary/` (JARs, plugins, extensions).

## Tests

Tests use JUnit 5 and live in `/test/`. There is no dedicated test runner script — run tests through your IDE or a JUnit runner with the classpath from `src/scripts/lib/`.

## Code Style (Checkstyle)

Checkstyle 10 enforces style on all **new** source files. Existing files are grandfathered
in `config/checkstyle-suppressions.xml` and are exempt until cleaned up.

```bash
# Report violations (never fails the build — good for local inspection)
ant checkstyle

# Strict mode — fails the build on any violation (use in CI)
ant checkstyle-strict

# CLI equivalent (exit code = number of errors; 0 = clean)
java -jar tools/checkstyle.jar -c config/checkstyle.xml \
-p config/checkstyle.properties src/graphtea
```

Key rules enforced on new code (`config/checkstyle.xml`):
- Braces required on all `if`/`for`/`while` bodies (`NeedBraces`)
- No `==` for string comparison (`StringLiteralEquality`)
- No unused or redundant imports
- `L` suffix on long literals, not `l`
- One statement per line; array brackets on type (`String[]` not `String []`)
- Whitespace around operators and after keywords
- Modifier order (`public static final`, not `static public final`)
- Complexity limits: cyclomatic ≤ 15, nesting depth ≤ 4

To **add a new file** to the suppression baseline (only if truly needed):
```xml
<!-- in config/checkstyle-suppressions.xml -->
<suppress files="MyNewFile.java" checks=".*"/>
```
Prefer fixing violations over suppressing them.

## Architecture

GraphTea is a **Java Swing desktop application** for graph theory, built around a plugin-extension architecture.

### Core Concepts

**BlackBoard** (`src/graphtea/platform/core/BlackBoard.java`)
The central event bus and state store. All inter-component communication flows through it. Components call `blackboard.setData(key, value)` to publish and `blackboard.addListener(key, listener)` to subscribe. This replaces direct dependencies between plugins.

**Plugin System** (`src/graphtea/platform/plugin/Plugger.java`)
Plugins are JAR files in `binary/plugins/`. Each JAR's manifest declares `plugin-name`, `plugin-version`, and `plugin-depends`. Plugger resolves load order via DFS topological sort. Each plugin has an `Init` class at `graphtea.plugins.<name>.Init` (or a custom manifest-specified class).

**Extension System** (`src/graphtea/platform/extension/`)
Extensions are JARs in `binary/extensions/`, dynamically loaded at startup. They implement typed interfaces:
- `AlgorithmExtension` — graph algorithms
- `GraphGeneratorExtension` — graph generators
- `ReportExtension` — computed graph properties/reports
- `ActionExtension` — graph transformations (products, line graphs, etc.)

### Module Layout

| Package | Role |
|---|---|
| `graphtea.platform` | Bootstrapping, BlackBoard, plugin/extension loading, preferences |
| `graphtea.graph` | Core graph model (`GraphModel`, `Vertex`, `Edge`), rendering, events |
| `graphtea.library` | Pure graph algorithm library, utilities |
| `graphtea.plugins` | Main UI, visualization, generators, algorithm animator, reports UI |
| `graphtea.extensions` | Concrete algorithms, generators, reports, actions (the bulk of domain logic) |
| `graphtea.ui` | Swing UI components: property editors, sidebars, menus |
| `graphtea.samples` | Example extension implementations |

### Entry Point

`graphtea.platform.Application.main()` → initializes BlackBoard → loads Preferences → loads Plugins (from `binary/plugins/`) → loads Extensions (from `binary/extensions/`) → fires `POST_INIT_EVENT`.

### Adding a New Extension

1. Implement the appropriate interface (e.g., `ReportExtension<GraphModel, String>`).
2. Build it as a JAR and drop it in `binary/extensions/`.
3. See `src/graphtea/samples/` for working examples.
117 changes: 115 additions & 2 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,71 @@
<description>
The ant build file of GraphTea Project.
</description>
<target name="test">
<property name="m2.repo" value="${user.home}/.m2/repository"/>
<property name="junit5.api" value="${m2.repo}/org/junit/jupiter/junit-jupiter-api/5.9.3/junit-jupiter-api-5.9.3.jar"/>
<property name="junit5.engine" value="${m2.repo}/org/junit/jupiter/junit-jupiter-engine/5.9.3/junit-jupiter-engine-5.9.3.jar"/>
<property name="junit5.platform.engine" value="${m2.repo}/org/junit/platform/junit-platform-engine/1.9.3/junit-platform-engine-1.9.3.jar"/>
<property name="junit5.platform.commons" value="${m2.repo}/org/junit/platform/junit-platform-commons/1.9.3/junit-platform-commons-1.9.3.jar"/>
<property name="junit5.platform.launcher" value="${m2.repo}/org/junit/platform/junit-platform-launcher/1.9.3/junit-platform-launcher-1.9.3.jar"/>
<property name="opentest4j" value="${m2.repo}/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar"/>

<target name="test" depends="compile" description="Compile and run JUnit 5 tests">
<mkdir dir="${basedir}/build/test-classes"/>
<javac srcdir="${basedir}/test" destdir="${basedir}/build/test-classes"
source="11" target="11" includeantruntime="false">
<classpath>
<path refid="project.lib"/>
<pathelement location="${basedir}/build"/>
<pathelement location="${junit5.api}"/>
<pathelement location="${opentest4j}"/>
<pathelement location="${junit5.platform.commons}"/>
</classpath>
<include name="GraphModelTest.java"/>
<include name="GraphUtilsTest.java"/>
<include name="GraphOperationsTest.java"/>
<include name="TraversalTest.java"/>
<include name="BasicReportsTest.java"/>
<include name="GeneratorsTest.java"/>
<include name="ProductsTest.java"/>
<include name="ReportsTest.java"/>
<include name="TestActions.java"/>
<include name="TestChemicalGraphIndices.java"/>
<include name="TestHomomorphism.java"/>
<include name="TestNewEdge.java"/>
<include name="AlgorithmsTest.java"/>
</javac>
<junitlauncher haltOnFailure="false" printSummary="true">
<classpath>
<path refid="project.lib"/>
<pathelement location="${basedir}/build"/>
<pathelement location="${basedir}/build/test-classes"/>
<pathelement location="${junit5.api}"/>
<pathelement location="${junit5.engine}"/>
<pathelement location="${junit5.platform.engine}"/>
<pathelement location="${junit5.platform.commons}"/>
<pathelement location="${junit5.platform.launcher}"/>
<pathelement location="${opentest4j}"/>
</classpath>
<testclasses outputdir="${basedir}/build/test-classes">
<fileset dir="${basedir}/build/test-classes">
<include name="GraphModelTest.class"/>
<include name="GraphUtilsTest.class"/>
<include name="GraphOperationsTest.class"/>
<include name="TraversalTest.class"/>
<include name="BasicReportsTest.class"/>
<include name="GeneratorsTest.class"/>
<include name="ProductsTest.class"/>
<include name="ReportsTest.class"/>
<include name="TestActions.class"/>
<include name="TestChemicalGraphIndices.class"/>
<include name="TestHomomorphism.class"/>
<include name="TestNewEdge.class"/>
<include name="AlgorithmsTest.class"/>
</fileset>
<listener type="legacy-xml" outputdir="${basedir}/build/test-classes" sendSysOut="true" sendSysErr="true"/>
<listener type="legacy-plain" sendSysOut="true"/>
</testclasses>
</junitlauncher>
</target>
<!-- - - - - - - - - - - - - - - - - -
target: depends
Expand Down Expand Up @@ -65,7 +129,7 @@
target: compile
================================= -->
<target name="compile" depends="depends" description="--> The ant build file of GraphTea Project.">
<javac srcdir="${src.dir}" destdir="${build.dir}">
<javac srcdir="${src.dir}" destdir="${build.dir}" source="11" target="11" includeantruntime="false">
<classpath>
<path refid="project.lib"/>
</classpath>
Expand Down Expand Up @@ -270,6 +334,55 @@
<!--<gzip destfile="${basedir}/../developer_resources/binary.tar.gz" src="${basedir}/../developer_resources/binary.tar"/>-->
</target>

<!-- =================================
target: checkstyle
================================= -->

<!--
Checkstyle targets.

checkstyle — runs style checks and reports violations but never fails
the build. Use this to inspect the current state.
checkstyle-strict — same checks, fails the build on any violation. Use this
in CI or as a pre-commit gate.

Existing code is grandfathered via config/checkstyle-suppressions.xml.
Only files NOT listed there must comply.

CLI equivalent:
java -jar tools/checkstyle.jar -c config/checkstyle.xml \
-p config/checkstyle.properties src/graphtea
-->
<target name="checkstyle" depends="depends" description="Report Checkstyle violations (never fails build)">
<taskdef resource="com/puppycrawl/tools/checkstyle/ant/checkstyle-ant-task.properties"
classpath="${basedir}/tools/checkstyle.jar"/>
<mkdir dir="${build.dir}/checkstyle"/>
<checkstyle config="${basedir}/config/checkstyle.xml"
failOnViolation="false"
maxErrors="0"
maxWarnings="9999999">
<property key="config_loc" value="${basedir}/config"/>
<formatter type="plain"/>
<formatter type="xml" tofile="${build.dir}/checkstyle/report.xml"/>
<fileset dir="${src.dir}" includes="graphtea/**/*.java"/>
</checkstyle>
<echo message="Checkstyle report written to ${build.dir}/checkstyle/report.xml"/>
</target>

<target name="checkstyle-strict" depends="depends" description="Run Checkstyle; fail build on any violation">
<taskdef resource="com/puppycrawl/tools/checkstyle/ant/checkstyle-ant-task.properties"
classpath="${basedir}/tools/checkstyle.jar"/>
<mkdir dir="${build.dir}/checkstyle"/>
<checkstyle config="${basedir}/config/checkstyle.xml"
failOnViolation="true"
maxErrors="0">
<property key="config_loc" value="${basedir}/config"/>
<formatter type="plain"/>
<formatter type="xml" tofile="${build.dir}/checkstyle/report.xml"/>
<fileset dir="${src.dir}" includes="graphtea/**/*.java"/>
</checkstyle>
</target>

<!-- =================================
target: clean
================================= -->
Expand Down
Loading
Loading