InfiniteProgressPanel inside a Netbeans RCP TopComponent

January 3rd, 2009

Anyone doing some serious work with Swing must have heard about the SwingFX API. This API contains some mightily cool GUI hacks, and I am particularly fond of Romain Guy’s infinite progress panel. So as a naive Java, Swing, NetBeans RCP programmer, I set out to use InfiniteProgressPanel to decorate the lenghty operations in my thesis project, AgentSpotter, the profiler for the MASs. Unsurprisingly, it did not work out of the box and required some understanding of the UI threading issues in Java, notably because I was working inside a NetBeans RCP TopComponent. In the end I managed to get the progress panel to work correctly, and I have encapsulated the logic in the following class:

public abstract class LenghtyOperationRunner
implements Runnable
{
  Component _oldPane;

  public LenghtyOperationRunner()
  {
  }

  public void run()
  {
    startProgress();

    Thread longOp = new Thread(new Runnable()
     {
         public void run()
         {
             doFirstPart();
             SwingUtilities.invokeLater(
              new Runnable()
              {
                  public void run()
                  {
                      doFinalPart();
                      stopProgress();
                  }
              });
         }
     });
    longOp.start();
  }

  private void stopProgress()
  {
    final JFrame mainWin =
      (JFrame) WindowManager.getDefault().getMainWindow();
    final PerformanceInfiniteProgressPanel p =
      (PerformanceInfiniteProgressPanel) mainWin.getGlassPane();
    p.setVisible(false);
    mainWin.setGlassPane(_oldPane);
  }

  private void startProgress()
  {
    final JFrame mainWin =
      (JFrame) WindowManager.getDefault().getMainWindow();
    _oldPane = mainWin.getGlassPane();
    PerformanceInfiniteProgressPanel glassPane;
    mainWin.setGlassPane(glassPane =
      new PerformanceInfiniteProgressPanel());
    glassPane.setVisible(true);
  }

 // Extension points:
 // override these methods
 // with the worker code

  protected abstract void doFirstPart();

  protected abstract void doFinalPart();

}

I have used PerformanceInfiniteProgressPanel, tweaked by Henry Story, instead of the standard InfiniteProgressPanel for performance reasons (would you expect something else from a profiling tool?). The implementation introduced by Romain in his original post was quite CPU intensive but it was subsquently improved by different SwingFX contributors.

The following code (adapted from here) shows how to use the class in a TopComponent:

class CallGraphTopComponent  extends TopComponent {
  private CallGraphTopComponent()
  {
      // This will launch the lenghty operation
      SwingUtilities.invokeLater(new CallGraphLoader());
  }

  private class CallGraphLoader
    extends LenghtyOperationRunner
  {
    JComponent treeview;

    @Override
    protected void doFirstPart()
    {
     // Start the main task here

      final ProgressHandle progress =
        ProgressHandleFactory.createHandle("Call Graph");
      ProgressHandler progressHandler = new ProgressHandler()
      {
        ... BLAH ...
      };

  // This is the lenghty operation
      treeview = CallGraph.newInstance(progressHandler);
    }

    @Override
    protected void doFinalPart() throws HeadlessException
    {
      // Things to run when the first part is finished

        if (treeview == null)
            JOptionPane.showMessageDialog(null,
              "Cannot create call graph tree view.");
        add(treeview);
    }
  }
}

To summarize, here are the steps to follow:

  • Subclass the LenghtyOperationRunner class listed here.
  • Override doFirstPart() and doFinalPart().
  • SwingUtilities.invokeLater() an instance of your custom runner wherever you want to display the progress panel while doing a lenghty operation. Et voilà!

Savvy readers will have noticed the use of SwingUtilities.invokeLater() which is the standard way to interact with the Java GUI event queue. The idea is to make sure that the main task code does not hog the CPU and leaves some breathing space for the UI thread which animates the panel. To this end, we must create a thread for the main task (doFirstPart()) which in turn must run any action that interacts with the UI in a new thread (doFinalPart()).

It must be noted that I tried to follow the steps described in this article first but it didn’t work for me. However you can still refer to this article to get more details on the mechanics of the progress panel.

Ultimately, I certainly have spent more time trying to make this panel work than I would have expected in the first place, but it was worth it because the bottom line is: the infinite progress panel is damn cool!

<french>

Le code présenté dans cet article décrit comment utiliser InfiniteProgressPanel dans une application NetBeans. Le secret est d’enchaîner correctement les appels à SwingUtilities.invokeLater() pour ne pas interférer avec le thread principal.

</french>

Pascal subprocedures in C#

December 31st, 2008

Sometimes I miss the embedded procedures feature of Object Pascal. OOP purists will throw a fit at this, but I know that the true Delphi fans will smile. Here’s the one liner delegate declaration required to implement subprocedures in C#:

/// <summary>
/// Use this delegate to simulate a pascal sub procedure i.e.
/// 
/// void OuterFunc() {
///     SubProcedure InnerProc = delegate() { ... };
/// 
///     ...
///     InnerProc();
///     ... 
///     InnerProc();
///     ...
/// }
/// </summary>;
public delegate void SubProcedure();

<french>

Les vrais fans de Delphi et de la programmation structurée conviendront avec moi que les sous-procédures sont bien cools. La simple déclaration de delegate décrite plus haut suffit pour émuler cette construction en C#.

</french>

La constitution du Dinhostan

December 16th, 2008

Je suis bien occupé ces derniers temps à la réalisation en collaboration avec mon ami Stan de notre site web, dinhostan.com. Notre idée est d’inventer un pays imaginaire, le “Dinhostan”, pour lequel nous avons créé une constitution, un drapeau, une carte etc. Stan est un graphiste hors pair, il a notamment gagné un concours pour la typo de la Smart (la petite voiture): c’est sûr, notre site sera magnifique!

TADA!

November 1st, 2008

I have submitted my Masters thesis today! It was pure adrenaline during the past month, but it was well worth the effort.

The problem is that I am so wound up that I can’t prevent myself from working a little bit more on AgentSpotter. So I have created a Java Web Start aka JNLP version that you can launch from here.

AgentSpotter beta

October 6th, 2008

Today I demoed AgentSpotter to Rem, my thesis supervisor, and he was really pleased so he gave me the green light for the final write up. I’d like to say that it’s just a formality now, unfortunately writing is much harder than programming for me. However I feel much lighter now that the coding part was signed off, and I think the last mile won’t be too stressful after all.

I am so proud of what I have achieved at this stage. I knew I wasn’t a bad programmer, but what I did on AgentSpotter was good beyond my own expectation. I felt like a Jedi drawing on all his accumulated experience and wisdom to write a program using an unfamiliar language, an unknown platform and a completely experimental domain. Coding was like eating peanuts, once I had started, it was very hard to stop.

Well, I have to stop coding now and start writing. Actually I think I’ll enjoy that immensely too because the concepts are really cool and I really want to share them with the world (read: the only 3 people in the world that are interested in profiling for multiagent systems)!

Alefa! — like we say in malagasy.

Snapshot of AgentSpotter main features

Snapshot of the beta version of AgentSpotter

L’art de la présentation

October 5th, 2008

Moi aussi je veux apprendre à faire ça!

En tout cas ça m’a bien relaxé après un weekend de coding frénétique sur AgentSpotter.

Update: fixed the mad link

AgentSpotter alpha is out!

September 23rd, 2008

Despite my rusty Java skills I managed to produce the first version of AgentSpotter my Master’s project which is a profiler for the MASses (multi-agent systems).

The deadly combination of SQLite, Netbeans Platforms and Piccolo has allowed me to create a first useful version of my tool with a cool zoomable UI and a professional touch lent by the Netbeans application framework.

Bragging rights

I am aware that this profiler thingy is a little bit obscure for most people including my wife Stéphanie. But this is, as far a I know, the first occurence of such a tool. There are gazillions of MAS visualisation tools out there but AgentSpotter is the first to display performance data: flat profiles, call graphs, space-time diagram. You name it, we have it! So that’s doubly cool and that’s something I can boast about at the watercooler.

Java Love

Smalltalk is by far my favourite OOP language, then Ruby, then C# and C++. I have used Java for some university assignments in 1998 and it was OK but I wasn’t impressed, C++ was far more interesting or OCAML. These last 2 years I have used Java again and AgentSpotter is my first major project in Java. Actually I like Java as much as C#. Nifty stuff like inner classes make it quite fun to use and the new C# language constructs are cool. I don’t like the generics implementation though, it feels less natural than the C# one. Anyway, this is a great opportunity for me to discover for myself why 90% of my Master’s colleagues are Java programmers.

At the end of day, Smalltalk is the best OOP system and language ever, but that’s another story!

Downloading AgentSpotter Station

You can download it from here. NOTE: you need the JDK or JRE 1.6 to be able to run it. MacOS users will want to try the mac version.

To be able to test the application, you will need a sample snapshot file. Download this one and save it somewhere on your hard drive so that you can load it into the AgentSpotter Station.

Building From Source

The full code is available from sourceforge.

Projects under trunk:

  • AFBenchmark — test application used to generate sample snapshots
  • AF-RTE — local copy of the runtime (SVN “cheap” copy)
  • AgentSpotterFile — snapshot file handling and querying library
  • AgentSpotterVisualisation — main UI library (space time diagram implementation)
  • AgentSpotterStation — main netbeans platform based application

The code should build out of the box using Netbeans 6.1+ (it works on my 2 machines :-) Just open the AgentSpotterStation project folder inside Netbeans and build it.

If you use Netbeans 6.5 beta, you have to change agentspotter/trunk/src/AgentSpotterStation/nbproject/platform.properties so that “enabled.clusters” contains “platform9″ instead of “platform”.

Pictures

This is a picture of the first concept dated from May 2008:

Here’s a screenshot of the actual application:

The realisation is much better than the idea. The zoomable UI is lots of fun to use, holding the mouse allows you pan or zoom (right button). I even added a “Bird’s Eye” view.

And here is the final touch, the cheesy logo! (I will ask my friend Stan to design a better one…)

Quick User Guide

After the first startup two windows will be open on the left hand side:

  • The Snapshot Explorer
  • The Bird’s Eye View

To load an existing snapshot file, right click on the “AgentSpotter Snapshots” root folder in the Snapshot Explorer and select “Add”. Use the displayed dialog to select “profile.aspot” for example.

Once the the snapshot is loaded you will have access to the different recorded sessions.

For each session the context menu contains the following options:

  • Open: display the Summary Window.
  • View: display the Space-Time Diagram.

The Summary Window contains a bunch of JTables that provide synthetised information about the session. The most interesting of course is the flat profile which reports the most CPU hungry agents.

The Space-Time diagram is a Zoomable User Interface:

  • Double clicking with the left mouse button will zoom into a component.
  • Double clicking with the right mouse button will zoom back to the parent or container of a component.
  • Right clicking and holding the button while moving the mouse will zoom in or out.
  • Left clicking and holding the button while moving the mouse will pan the view.
  • Hovering over a component (message send/receive, message line, agent name etc.) will popup a yellow tooltip.
  • Click in the Bird’s View Window and move the viewport to navigate in the diagram. You may have to move/resize the window to get the desired effect!

Building Agent Factory in NetBeans 6.1

August 17th, 2008

After nearly 2 years of hard work, I am not done yet with my Master’s degree in Advanced Software Engineering because I still have a project to complete and a dissertation to write. I have chosen to work on a great multiagent system (MAS) development toolkit called Agent Factory, developed and maintained at my university, UCD. Even if it is a research project, Agent Factory is quite usable and is improved all the time. For my dissertation, I will have to extend the existing code to include a performance measurement infrastructure that will provide data for the MAS performance analysis I am planning to implement. So I have downloaded the code and I have begun to play with it. Not being a Java head I had some difficulty getting NetBeans to build properly the full system. The problem was me and my understanding of course, not the code which has perfectly up to date Ant build scripts. So after a full afternoon of fumbling around I managed to get everything to build smoothly and I thought that for the non-Java people around there, it could be nice to have a quick startup guide.

So, after downloading the Agent Factory source code from the CVS how do you build it? Well, it depends if you are using an IDE or Ant. But first you have to understand the build architecture. The first level module is the runtime environment, “AF-RTE”. This module does not reference any other component than the standard Java APIs. Then comes the Debugger runtime, “AF-Debugger”, and the common release APIs, grouped under “Common”, that both need only “AF-RTE”. Finally the Agent Factory development kit, “AFAPL2-DK”, references all the modules we have just cited. There are also a bunch of secondary modules that do not change much: “HTPP-MTS”, “Local-MTS” etc. Note that I do not include “AF2ME” in this tutorial, but basically you should be able to apply the recipes I am describing here.

If you want to use Ant only, then you can compile a module by going into the corresponding directory and type “ant compile” or “ant release” if compile is not available. You have to make sure that the “af-release” property defined in the “build.properties” files are consistent because the build system uses the provided value to build JAR file names that are referenced by the compilation targets. In other words, just make sure all the “af-release” properties are set to the same value throughout the properties files. There is a special build file in the “full-build” module that goes through all the projects. My advice is to read carefully the Ant build files to discover where the files are output.

If you want to use an IDE, which is more likely, the idea is that you want reproduce the dependencies described earlier. Here’s the detail of my NetBeans 6.1 configuration procedure to give you an idea of what you need to do. First I have added “AF-RTE” as a NetBeans Java project with existing source code. I specified the “$YOURPATH/AF-RTE/src” full path as the only source package folder (Note: replace $YOURPATH with the path you’re using). No other configuration step is required as “AF-RTE” depends only on the standard Java APIs. I added “AF-Debugger” the same way, pointing “$YOURPATH/AF-Debugger/src” as the source package folder, but this time I added the output of the “AF-RTE” project, “$YOURPATH/AF-RTE/dist/AF-RTE.jar”, as a compile-time library (you can also point to “$YOURPATH/AF-RTE/build/classes”.)

The “Common” module must be added as a “Java Free-form project” based on the existing Ant build file. In the “New Java Free-Form Project” wizard dialog, specify the path “$YOURPATH/Common” as the project location and “$YOURPATH/Common/build.xml” as the build script. Then select “compile” or “release” as the action for building the project. Finally add the different “src” folders as source package folders. After validating the wizard, display the properties of the new project to add some additional information to the “Java Sources Classpath” category. Make sure “Separate Classpath for Each Source Package Folder” is checked, then add the classpaths as follows:

  • Compatibility/src: add “$YOURPATH/Common/Logic/build/classes” and “$YOURPATH/AF-RTE/build/classes”.
  • Logic/src: add “$YOURPATH/AF-RTE/build/classes”.

Do the same for the “AFAPL2-DK” project with the following dependency settings:

  • Compiler/src: add “$YOURPATH/Common/Logic/build/classes” and “$YOURPATH/AF-RTE/build/classes”.
  • Core/src: add “$YOURPATH/AFAPL2-DK/Interpreter/build/classes”, “$YOURPATH/Common/Logic/build/classes” and “$YOURPATH/AF-RTE/build/classes”.
  • Debugger/src: add “$YOURPATH/AFAPL2-DK/Interpreter/build/classes”, “$YOURPATH/Common/Logic/build/classes” and “$YOURPATH/AF-RTE/build/classes”.

The following screenshots show what you should obtain the project properties pages for the AFAPL2-DK project:

List of Source Package Folders for AFAPL2-DK

List of Source Package Folders for AFAPL2-DK

Classpath example for the Core AFAPL2-DK package

Classpath example for the Core AFAPL2-DK package

Do the same for the other modules you require like “HTTP-MTS” or “Infrastructures”, et voilà, you should obtain the following Project view in NetBeans:

Final list of projects

Final list of projects

I know that hardcore Java heads will find all this perfectly obvious and redundant, but I didn’t write this article for them so all is well. And no, this is not dogwash.

Tweaking the output of XSD.exe to use generics

August 20th, 2007

A program I am working on heavily uses XML deserialization to build object models from XML files.

I didn’t have to write the deserialization code thanks to the excellent tool provided by Microsoft called XML Schema Definition Tool (Xsd.exe). This tool generates a bunch of C# classes that capture the data structure described in a given schema file (XSD files).

The generated code do have a few shortcomings though, like the use of arrays to handle multiple elements or the generation of FxCop unfriendly code. Jonathan ‘Peli’ de Halleux has already solved most of these problems in his XsdTidy, XSD mapping beautifier tool.

In my case, XsdTidy didn’t really work out of the box. My problems where slightly different:

  • Use generics for multiple elements instead of array, e.g. List<sometype> instead of SomeType[].
  • Use a tool runnable from the command line to integrate easily in my automated build system.

I could have hacked XsdTidy to solve these problems, but instead I went for the bad and the ugly: a quick and dirty regex script. I could have used perl, python or any other language that has a reasonably powerful regex engine, but I really have a soft spot for ruby. So here it goes, tweakXsd.rb, a quick and dirty, one-off job to tweak an xsd-generated class file to use generics.

Everytime I change my XSD schema files, I run a the MS-DOS script like the one below to regenerate C# classes, et voilà!

    REM 
    REM This script generates Foo.cs from Foo.XSD
    REM
    SET XSD="C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin\xsd.EXE"
    SET RUBY=C:\ruby\bin\ruby.exe
    %XSD% /c /namespace:My.Namespace /order Foo.xsd 
    %RUBY% tweakXsd.rb < Foo.cs > Foo.cs.tmp
    del Foo.cs
    ren Foo.cs.tmp Foo.cs

As a bonus, the script tweaks elements defined as XmlTextAttribute to string properties instead of string[]. To produce a XmlTextAttribute compatible element, use the following schema declaration:

 <xs:element name="elementWithText">
   <xs:complexType mixed="true" />
 </xs:element>

<french>

L’outil Xsd.exe proposé par Microsoft pour la création de classes de désérialisation XML à partir d’un fichier de schéma XML est réellement très utile. Le seul problème c’est que le code généré utilise des tableaux pour permettre l’accès aux collections d’éléments. Pour un projet je souhaitais pouvoir accéder à ces collections en utilisant des collections génériques de type List<T>. Après avoir écarté l’outil XsdTidy j’ai codé moi-même un script en mode “porcho” (cf. le Dictionnaire vosgien-français).

Le script tweakXsd.rb prend en entrée le résultat de “xsd.exe /c” et produit une version modifiée qui utilise les génériques et expose les attributs taggés XmlTextAttribute en tant que propriétés de type string au lieu de string[].

Le script MS-DOS cité plus haut montre un exemple d’automatisation du script.

</french>

Rounding to a factor in Transact SQL

August 14th, 2007

Straight port from VBA routines written by Dejan Mladenovic.

Very useful to round to a quarter of a day for example. The following query should yield 12.75:

   SELECT dbo.FN_RoundNear(12.63, 0.25)

You can download the script here.

<french>

Portage vers SQL Server d’un code VBA qui permet d’arrondir un nombre à un multiple donné. C’est le genre de truc qu’on faisait au collège en 6ème, et pourtant c’est bien pratique de le trouver pré-mâché!

P.S.: la syntaxe de TSQL est vraiment laide à pleurer.

</french>

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION FN_RoundUpDown
(
   @nb FLOAT,
   @factor FLOAT
)
RETURNS FLOAT
AS
BEGIN
-- ***********
-- Name:      FN_RoundUpDown (Function)
-- Purpose:   round @nb to @factor, up or down
-- Inputs:    @nb = number to round
--            @factor  = rounding precision
--           +@factor = rounds UP
--           -@factor = rounds DOWN
-- Example:   FN_RoundUpDown(5.12,+0.25) = 5.25
--            FN_RoundUpDown(5.12,-0.25) = 5.00
-- Output:    @nb rounded UP/DOWN
-- ***********
  DECLARE @result FLOAT
  DECLARE @temp_nb FLOAT
  SET @temp_nb = @nb / @factor
  IF (FLOOR(@temp_nb) - @temp_nb) = 0
    SET @result = @nb
  Else
    SET @result = FLOOR((((@nb + (2 * @factor)) / @factor) - 1)) * @factor
  RETURN @result
END
GO
CREATE FUNCTION FN_RoundNear
(
   @nb FLOAT,
   @factor FLOAT
)
RETURNS FLOAT
AS
BEGIN
-- ***********
-- Name:      FN_RoundNear (Function)
-- Purpose:   rounds @nb to the nearest fraction equal 
--            @factor
-- Inputs:    @nb - number to round
--            @factor - the fraction used as measure of 
--            rounding
-- Example:   FN_RoundNear(53,6) = 54
--            FN_RoundNear(1.16,0.25) = 1.25
--            FN_RoundNear(1.12,0.25) = 1.00
--            FN_RoundNear(1.125,0.25)= 1.25
-- Output:    @nb rounded to nearest
--            multiple of @factor.
-- ***********
  DECLARE @result FLOAT
  DECLARE @decValue FLOAT
  DECLARE @intX INT
  DECLARE @divX FLOAT

  SET @divX = @nb / @factor
  SET @intX = FLOOR(@divX)
  SET @decValue = @divX - @intX

  IF @decValue >= 0.5
    SET @result = @factor * (@intX + 1)
  Else
    SET @result = @factor * @intX  

  RETURN @result
END
GO