Wednesday, February 26, 2014

Adding a list editor in eclipse preference. Extend ListEditor

Adding a list editor in Eclipse preferences implies to extend ListEditor.
This  post concern the build of a ListEditor dealing with filter definition relying on regular expression.


The beginning,  create a FilterDialog

This dialog aims to get a filter entry. This dialog should return a String containing a regular expression. (I don't verify that the content typed is OK but I will)


the FilterDialog source code :

import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class FilterDialog extends TitleAreaDialog {

  private Text filterValue;

  private String filter;

  public FilterDialog(Shell parentShell) {
    super(parentShell);
  }

  @Override
  public void create() {
    super.create();
    setTitle("Add filter to keep tests");
  }

  @Override
  protected Control createDialogArea(Composite parent) {
    Composite area = (Composite) super.createDialogArea(parent);
    Composite container = new Composite(area, SWT.NONE);
    container.setLayoutData(new GridData(GridData.FILL_BOTH));
    GridLayout layout = new GridLayout(2, false);
    container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    container.setLayout(layout);
    createFilter(container);
    return area;
  }

  private void createFilter(Composite container) {
    Label lbtFirstName = new Label(container, SWT.NONE);
    lbtFirstName.setText("Filter as regular expression");

    GridData dataFirstName = new GridData();
    dataFirstName.grabExcessHorizontalSpace = true;
    dataFirstName.horizontalAlignment = GridData.FILL;

    filterValue = new Text(container, SWT.BORDER);
    filterValue.setLayoutData(dataFirstName);
  }

  @Override
  protected boolean isResizable() {
    return true;
  }
 
  private void saveInput() {
    filter = filterValue.getText();
  }

  @Override
  protected void okPressed() {
    saveInput();
    super.okPressed();
  }

  public String getFilter() {
    return filter;
  }
 
} 

Extend ListEditor


the source code :
import java.io.File;

import org.eclipse.jface.preference.ListEditor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Composite;


public class FilterTestEditor extends ListEditor {

    protected FilterTestEditor() {
    }

    public FilterTestEditor(String name, String labelText, Composite parent) {
        init(name, labelText);
        createControl(parent);
    }

    protected String createList(String[] items) {
        StringBuffer path = new StringBuffer("");//$NON-NLS-1$
        for (int i = 0; i < items.length; i++) {
            path.append(items[i]);
            path.append(File.pathSeparator);
        }
        return path.toString();
    }


    protected String getNewInputObject() {
     String filter=null;
        FilterDialog dialog = new FilterDialog(getShell());
        dialog.create();
       
        if (dialog.open() == Window.OK) {
           System.out.println(dialog.getFilter());
           filter = dialog.getFilter();
         } 
        return filter;
    }
    
    protected String[] parseString(String stringList) {
  StringTokenizer sto = new StringTokenizer(stringList, File.pathSeparator
                + "\n\r");
        ArrayList<String> v = new ArrayList<String>();
        while (st.hasMoreElements()) {
            v.add((String) sto.nextElement());
        }
        return (String[]) v.toArray(new String[v.size()]);
    }
}

and finally in the préférence page add

addField(new FilterTestEditor(KEY_FILTER_TEST, "Test filtering", getFieldEditorParent()));

Running external tools programmatically with eclipse

Small tutorial for running external tools programmatically with eclipse

Last couple of day I had to refactor code for an eclipse plugin.
The source code to modify rely on java runtime exec to launch a temporary maven project. This code works fine but the process launched does not log in eclipse console.
So at this point I look for a way to launch this maven build, external to the workspace as the eclipse menu "launch external tool does". After a few search on the web I found a way to be able to do this:
  • create a launch configuration
  • save it in a file
  • build the same setup in source code
  • and finally launch the configuration

First thing to do : create an external tool configuration...
saved in a file (see Shared file field)

Run this configuration.

You should find a file in the root folder project named : New_configuration.launch.
Now when editing this file I have all the parameters needed to write my code :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" 
 value="${system_path:mvn.bat}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" 
 value="-Dlogback.configurationFile=customlogback.xml -U clean install exec:java"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" 
 value="D:\DONNEES\FDS_DATA\genDoc"/>
</launchConfiguration>

With this content and this address I could now write the source code that allow me to launch programmatically my temporary maven project.
A nice point here, you could rely on eclipse variable (like ${system_path:mvn.bat})  
//to be able to listen the end
manager.addLaunchListener(this);
ILaunchConfigurationType type = manager
  .getLaunchConfigurationType("org.eclipse.ui.externaltools.ProgramLaunchConfigurationType");
ILaunchConfiguration[] configurations = manager
  .getLaunchConfigurations(type);
for (int i = 0; i < configurations.length; i++) {
 ILaunchConfiguration configuration = configurations[i];
 if (configuration.getName().equals("Gen doc")) {
  configuration.delete();
  break;
 }
}
ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(
  null, "Gen doc");
String exec = "mvn.sh";
if (nameOS.toLowerCase().contains("win")) {
 exec = "mvn.bat";
}
workingCopy.setAttribute(
  "org.eclipse.ui.externaltools.ATTR_LOCATION",
  "${system_path:" + exec + "}");
workingCopy.setAttribute(
  "org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS",
  "-Dlogback.configurationFile=genDoclogback.xml -U clean install exec:java");
workingCopy.setAttribute(
  "org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY",
  tmpGenDir.getCanonicalPath());
ILaunch launch = workingCopy.launch(ILaunchManager.RUN_MODE,
  new NullProgressMonitor());
//to retreive the launched project at the end
launchProject.put(launch, project);

and to be able to listen the end of your launch configuration implement "ILaunchesListener2" and add

@Override
public void launchesTerminated(ILaunch[] launches) {
 for (ILaunch launch : launches) {
  Project project = launchProject.get(launch);
  if (project != null) {
   launchProject.remove(launch);
   //if needed...
   Display.getDefault().asyncExec(new Runnable() {
    @Override
    public void run() {
     
    }
   });
  }
 }
}


Saturday, January 18, 2014

Raspbery-pi, Gertboard : building an oscilloscope


Playing with raspberry pi and gertboard (part one)

Last few years I follow the raspberry-pi initiative and I really much appreciate it. This year I decide to use this micro computer associated to a gertboard to acheive an old project : building a stand alone oscilloscope.

what I want to acheive :


Step one : where is my  hdmi screen ????

Using my Windows8 PC for raspberry export display

I don't want to use or buy a new HDMI display for this Raspberry pi experiment.
So I will use my own laptop. For the very first RP start, You need an HDMI to setup your RP.
  • Connect you RP  (Raspberry pi) 
  • With the setup screen activate SSH.
  • You could now power off RP and disconnect your HDMI screen.
  • Power on RP
  • Goes on your windows station and you had to install an XServer and ssh client  : you could use mobaxterm, cygwin or a Virtual box with a Linux ISO installed in it (network setup with bridge adapter).
  • With this client, open a terminal and connect your RP with ssh :
xhost +
ssh -X pi@ip_addr_of_remote_machine
# the password is rasberry

Use man xhost and man ssh for more information
You sould have something like that (with mobaxterm)


At this point you could access to your RP.

just use :
lxsession

After a few second a window should be open with the RP desktop.

How to access my ATmega on my gertboard?

Just have a look at https://projects.drogon.net/raspberry-pi/gertboard/arduino-ide-installation-isp/ this is the "Gordons Projects" blog wich is very well done. You will find out there all that you need for your gertboard.
I just need to add an apt-get update, and all works as expected.

 (to be continued)

Tuesday, October 22, 2013

OSGI Maven bundle for Eclipse (Part 2)

In a previous post I use maven-bundle plugin to expose maven artifact as OSGI bundle. I change a little my approach and now update the classpath manually. After using this setup for a while, I experiment one problem : How to convert maven plugin version including -SNAPSHOT to .qualifier ? After many search I found a solution using BND macro. You "just" have to put in "Bundle-Version" this macro :
<bundle-version>$(replace;${project.version};-SNAPSHOT;.qualifier)</bundle-version>

Wednesday, October 9, 2013

Sharing source through usb key and git

Aims :
Set up a git environment with for two desktops sharing source code through USB

Warning : all those commands have to be tested  before use. Check git documentation for more explanations.

git env creation on USB Key


using git-bash, in the repository folder do
$ git --bare init

git env creation on one desktop



using git-bash, in the source folder  do
$ git init
manage ignored ressources
create a .gitignore
$ git add .gitignore
$ git commit -m "ignored resource"
avoid conversion from LF to CRLF
$ git config core.autocrlf false 
$ git config --global user.name "yourName"
$ git config --global user.email yourEmail
commit your existing sources
$ git add --all
$ git commit -m "initial commit"

Add a remote repository (assuming the drive is f)
$ git remote add origin /f/path/to/repo/

Push sources
$ git push origin master

On the second desktop

using git-bash, in the source folder  do
$ git init
$ git remote add origin /f/path/to/repo/

pull sources
$ git pull origin master 

Tips


if you want to overide local changes
$ git fetch origin master
$ git reset --hard FETCH_HEAD

at this point local untrack file and dir still exists (see git clean)


Tuesday, September 17, 2013

Rich editor in eclipse RCP (Part2)


A few month ago I built a rich editor for eclipse based on SWT browser.
I use this implementation from this time and now I want to integrate it in an EMF (EEF generated) GUI.
In this context this widget needs a focus managment but the SWT Browser does not manage those events (See Javadoc (event) ).
In my case I decide to rely on TyneMCE events managment (blur and focus), then react on those events invoking a BrowserFunction that allows javascript to java communication. In java side  the Browser fonction notify an internal listener.

Rely on tinyMce events



those event are identified bty name : blur and focus. To be able to react to those events, add to your tiny init (JS) :
setup : function(ed) {

   ...

   ed.onInit.add(function(ed) {

     if (tinymce.isIE) {

       tinymce.dom.Event.add(ed.getWin(), 'focus', function(e) {

           evt_focusGained();

       });

       tinymce.dom.Event.add(ed.getWin(), 'blur', function(e) {

           evt_focusLost();

       });

   } else {

       tinymce.dom.Event.add(ed.getDoc(), 'focus', function(e) {

           evt_focusGained();

       });

       tinymce.dom.Event.add(ed.getDOc(), 'blur', function(e) {

           evt_focusLost();

       });

   }

   });

  },

Usage of BrowserFuntion


Browser function allow communication from javascript to java. Excerpt : "Instances of this class represent java-side "functions" that are invokable from javascript. Browser clients define these functions by subclassing BrowserFunction and overriding its function(Object[]) method. This method will be invoked whenever javascript running in the Browser makes a call with the function's name."

So I add in the completed method of the SWT browser progressListener :

browser.addProgressListener(new ProgressListener() {

 public void changed(ProgressEvent event) {

 }

 public void completed(ProgressEvent event) {

  // used for setEditorText

  completed = true;

  loadEditorText((String) browser.getData("htmlcontent"));

  new BrowserFunction(browser, "evt_focusLost") {

   public Object function(Object[] arguments) {

    notifyListenersFocusLost();

    return null;

   }

  };

  new BrowserFunction(browser, "evt_focusGained") {

   public Object function(Object[] arguments) {

    notifyListenersFocusGained();

    return null;

   }

  };

 }

});

In this implementation, you could see notifyListenersFocusLost() and notifyListenersFocusGained(). Those two methods relate to two listeners similar implementation.

public interface TinyFocusLostListener {

 public abstract void focusLost();

}

private List listenersTinyFocusLost = new ArrayList();



public void addTinyFocusLostListener(TinyFocusLostListener listenerValue) {

 listenersTinyFocusLost.add(listenerValue);

}

// Warning UI action use asyncexec in eclipse

private void notifyListenersFocusLost() {

 Display.getCurrent().asyncExec(new Runnable() {

  public void run() {

   for (TinyFocusLostListener listener : listenersTinyFocusLost) {

    listener.focusLost();

   }

  }

 });

}

finally on Java side

myTinyIntegrationInstance.addTinyFocusLostListener(new TinyFocusLostListener() {

 @Override

 public void focusLost() {

  //Add your code here

  }

 }

});

Friday, March 22, 2013

fast bulk data insert in Mysql

Last couple of week I have to work on a persistancy component.
The problematic was :

  • Import of huge data list ; from 500K itemes to 1.5M items
  • where items are ordered and contains a date, 
  • and  items contains 5 double.

The whole datas (not only those lists) have to be request in many ways and they are not all known, so we choose to test  a relational database system to offer large type of request .
As we have a Mysql 5.0 server install we decide to use this database.

To be able to progress we define many use case. The main use cases are :


  • Start from a text file containing datas (500k lines, tab separated) and Import those file in mysql
    • implies convert file to object
    • implies RDB INSERT request
  • Read those 500k items
    • implies RDB SELECT
  • Write in an another place those 500k items
    • implies convert SELECT result to object
    • implies RDB INSERT
The last two points fake a standard process for us : get datas, process results with previous datas, and finally push result. 

So we try many thing, using jdbc bridge and we progress while we read many post and article about "Fast  INSERT INTO " ; The list below is show starting from the worst performance in our case to the best.
  • using jdbc statment and default autocommit
    • one request for one line, commit each time
  • using jdbc statment , autocomit to false and then commit
    • one request for one line, commit each the end of lines process
  • using jdbc statment, addbatch, autocomit to false and then commit
    • one request for many lines lines (we use a batch size to preserve memory and spread RDB load) , commit
  • using jdbc prepareStatment and addbatch, autocomit to false and then commit
    • use RDB optimization when dealing many times the same request.
  • using LOAD DATA LOCAL INFILE using and ImputStream
    • we convert the file in an imput stream :
      • adding an order 
      • converting date format
      • giving an extenal id


Statement stmt = con.createStatement();
String statementText = "LOAD DATA LOCAL INFILE 'file.txt' "
  + "INTO TABLE tableEntry "
  + " (date, a, b, c, d, e, idx) "
  + " SET FK_ID ="
  + getExternalId();
InputStream is = readDataAsImpuStream(source);
((com.mysql.jdbc.Statement) stmt).setLocalInfileInputStream(is);
stmt.execute(statementText);


The request LOAD DATA LOCAL INFILE is specific to mysql and allows the best performance is our case (time divide  by 15). We have other thing to do optimize again our request time like :

  • RBD server setting
  • Modifyng table structure to reduce the number of fields
  • ....