Mittwoch, 23. Januar 2013

Nullpointerexception while editing data sets in Eclipse BIRT 4.2.1

Do you sometimes get null pointer exceptions while editing a data set in BIRT? Your error log states something like:

java.lang.NullPointerException
    at org.eclipse.datatools.sqltools.sqlbuilder.SQLBuilder.setControlStateSize(SQLBuilder.java:1287)
    at org.eclipse.datatools.sqltools.sqlbuilder.SQLBuilder.saveWindowStateInfo(SQLBuilder.java:1233)
    at org.eclipse.datatools.sqltools.sqlbuilder.SQLBuilder.getWindowStateInfo(SQLBuilder.java:1218)
    at org.eclipse.birt.report.data.oda.jdbc.dbprofile.ui.internal.sqb.SQLBuilderDesignState.createSQBInput(SQLBuilderDesignState.java:93)
    at org.eclipse.birt.report.data.oda.jdbc.dbprofile.ui.internal.sqb.SQLBuilderDesignState.(SQLBuilderDesignState.java:46)

...

or

java.lang.NullPointerException
    at org.eclipse.datatools.sqltools.sqlbuilder.SQLBuilder.setControlStateSize(SQLBuilder.java:1287)
    at org.eclipse.datatools.sqltools.sqlbuilder.SQLBuilder.saveWindowStateInfo(SQLBuilder.java:1233)
    at org.eclipse.datatools.sqltools.sqlbuilder.SQLBuilder.getWindowStateInfo(SQLBuilder.java:1218)
    at org.eclipse.birt.report.data.oda.jdbc.dbprofile.ui.internal.sqb.SQLBuilderDesignState.createSQBInput(SQLBuilderDesignState.java:93)
    at org.eclipse.birt.report.data.oda.jdbc.dbprofile.ui.internal.sqb.SQLBuilderDesignState.(SQLBuilderDesignState.java:46)

? Then I have a workaround hint for you: edit the file in XML, look for the dataset section that causes the problem and delete its whole section  . Save and after that, the nullpointer Exception should be gone. Make sure to have backups before you change anything so you can always roll back.


Freitag, 27. Juli 2012

Proof-reading Latex documents with Microsoft Word

It makes sense to proof read papers or articles in Microsoft Word as it provides a pretty good spell and grammar checker (as opposed to what is available for use with Latex). A method working pretty well for me is the following:

  • Include \usepackage{hyphenat} in your Latex project.
  • Surround all text in the Latex document with a \nohyphens{ } which forbids hyphenations.
  • Use NitroPDF or http://www.pdftoword.com to convert the Latex generated PDF to a Word .doc file.
  • The PDF to Latex converter often produces multiple white spaces after another. This is reported by the spell checker. To remove this problem, do the following:
    1. Ctrl+H
    2. Find what: enter ^w
    3. Replace with: enter a space
    4. Replace all.
  • To avoid ligatures (e.g., ff, fl, fi are one character) use the following package and configuration:
    \usepackage{microtype}
    \DisableLigatures{encoding = *, family = * }

    The nohypens step is useful, because the PDF to Word converter does not recognize words that have be hyphenated (or split) by Latex - they are interpreted as two word. Using the nohyphens block avoids this problem and there is considerably less to proof read and actual errors are easier to spot.
  • Donnerstag, 16. September 2010

    Greetings from Reykjavik

    A few pictures from Iceland...

    IMG_3003.jpg

     

    IMG_2939.jpg

     

    IMG_3064.jpg

    Mittwoch, 3. März 2010

    Eclipse Run Configurations under Snow Leopard

    Again a reminder for myself: when running the Eclipse App causes strange SWT errors and so on, try to pass in the VM argument "-d32". This is somehow a 64bit/32bit problem.

    Donnerstag, 25. Februar 2010

    Rename Refactoring for Xtext DSLs

    Today, i kind of finished hacking together a rename refactoring for an Xtext DSL i'm working on. It may be kind of messy in some places, but anyway, here it is. In a few places, it is DSL specific and so far it only processes the open file. But it should be easy to adapt (and clean up). Please feel free to copy, adapt, generalize or whatever.

    First, there is the rename processor "RenameProcessor.java":

    package mysomething.refactoring.rename;

    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Set;

    import org.eclipse.core.resources.IFile;
    import org.eclipse.core.resources.IProject;
    import org.eclipse.core.resources.IWorkspace;
    import org.eclipse.core.resources.IWorkspaceRoot;
    import org.eclipse.core.resources.ResourcesPlugin;
    import org.eclipse.core.runtime.CoreException;
    import org.eclipse.core.runtime.IPath;
    import org.eclipse.core.runtime.IProgressMonitor;
    import org.eclipse.core.runtime.OperationCanceledException;
    import org.eclipse.emf.common.util.URI;
    import org.eclipse.emf.ecore.EObject;
    import org.eclipse.emf.ecore.util.EcoreUtil;
    import org.eclipse.jface.text.ITextSelection;
    import org.eclipse.ltk.core.refactoring.Change;
    import org.eclipse.ltk.core.refactoring.CompositeChange;
    import org.eclipse.ltk.core.refactoring.RefactoringStatus;
    import org.eclipse.ltk.core.refactoring.TextFileChange;
    import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
    import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring;
    import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
    import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
    import org.eclipse.text.edits.MultiTextEdit;
    import org.eclipse.text.edits.ReplaceEdit;
    import org.eclipse.text.edits.TextEditGroup;
    import org.eclipse.xtext.parsetree.CompositeNode;
    import org.eclipse.xtext.parsetree.NodeAdapter;
    import org.eclipse.xtext.parsetree.NodeUtil;
    import org.eclipse.xtext.resource.EObjectAtOffsetHelper;
    import org.eclipse.xtext.resource.IEObjectDescription;
    import org.eclipse.xtext.resource.IReferenceDescription;
    import org.eclipse.xtext.resource.IResourceDescription;
    import org.eclipse.xtext.resource.IResourceDescriptions;
    import org.eclipse.xtext.resource.XtextResource;
    import org.eclipse.xtext.ui.core.editor.XtextEditor;
    import org.eclipse.xtext.util.concurrent.IUnitOfWork;
    import mysomething.Rule;
    import mysomething.RuleReference;
    import mysomething.utils.EObjectResolver;
    import mysomething.utils.URIFragmentResolver;

    import com.google.common.base.Predicate;
    import com.google.common.collect.Iterables;

    public class RenameProcessor extends
    org.eclipse.ltk.core.refactoring.participants.RenameProcessor {

    private XtextEditor editor;
    private IResourceDescriptions resourceDescriptions;
    private List<CompositeNode> references = null;
    private String currentName;
    private CompositeNode declaration;
    private IFile file;

    public RenameProcessor(XtextEditor editor,
    IResourceDescriptions resourceDescriptions) {
    this.editor = editor;
    this.resourceDescriptions = resourceDescriptions;

    final ITextSelection selection = (ITextSelection) editor
    .getSelectionProvider().getSelection();
    final IEObjectDescription eObjectDescription = editor.getDocument()
    .readOnly(new EObjectResolver(selection, resourceDescriptions));

    declaration = editor.getDocument().readOnly(
    new URIFragmentResolver(eObjectDescription.getEObjectURI()
    .fragment()));

    if (declaration.getElement() instanceof Rule) {
    Rule r = (Rule) declaration.getElement();
    currentName = r.getName();
    }

    file = (IFile) editor.getEditorInput().getAdapter(IFile.class);

    if (eObjectDescription != null) {
    references = findReferenceDescriptions(eObjectDescription);
    }

    }

    @Override
    public Object[] getElements() {
    return null;
    }

    @Override
    public String getIdentifier() {
    return "Rename Processor Identifier";
    }

    @Override
    public String getProcessorName() {
    return "Rename Processor";
    }

    @Override
    public boolean isApplicable() throws CoreException {
    return (references != null);
    }

    @Override
    public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
    throws CoreException, OperationCanceledException {
    RefactoringStatus status = new RefactoringStatus();

    if (references == null)
    status.addFatalError("Could not obtain references!");

    return status;
    }

    @Override
    public RefactoringStatus checkFinalConditions(IProgressMonitor pm,
    CheckConditionsContext context) throws CoreException,
    OperationCanceledException {
    RefactoringStatus status = new RefactoringStatus();
    RenameRefactoring refactoring = (RenameRefactoring) getRefactoring();
    if (currentName.equals(refactoring.getRenameText())) {
    status.addFatalError("Name unchanged!");
    } else if (refactoring.getRenameText().length() <= 0) {
    status.addFatalError("name must not be empty!");
    }

    return status;
    }

    @Override
    public Change createChange(IProgressMonitor pm) throws CoreException,
    OperationCanceledException {
    CompositeChange compositeChange = new CompositeChange("Rename");
    pm.beginTask("Rename Refactoring", references.size());

    MultiTextEdit multiEdit = new MultiTextEdit();
    TextFileChange fileChange = new TextFileChange("Declaraction Renaming", file);

    fileChange.setEdit(multiEdit);
    fileChange.setTextType("bnf");
    compositeChange.add(fileChange);

    RenameRefactoring refactoring = (RenameRefactoring) getRefactoring();
    String replaceText = refactoring.getRenameText();

    ReplaceEdit replaceEdit = new ReplaceEdit(declaration.getOffset(), ((Rule)declaration.getElement()).getName().length(), replaceText);
    multiEdit.addChild(replaceEdit);

    TextEditGroup editGroup = new TextEditGroup("declaration update", replaceEdit);
    fileChange.addTextEditGroup(editGroup);
    pm.worked(1);


    for (int i=0; i < references.size(); i++) {
    CompositeNode reference = references.get(i);

    replaceEdit = new ReplaceEdit(reference.getOffset(), ((Rule)declaration.getElement()).getName().length(), replaceText);
    multiEdit.addChild(replaceEdit);
    editGroup = new TextEditGroup("reference update", replaceEdit);
    fileChange.addTextEditGroup(editGroup);

    pm.worked(1);
    }

    return compositeChange;
    }

    @Override
    public RefactoringParticipant[] loadParticipants(RefactoringStatus status,
    SharableParticipants sharedParticipants) throws CoreException {
    return null;
    }

    private List<CompositeNode> findReferenceDescriptions(
    final IEObjectDescription eObjectDescription) {
    List<CompositeNode> references = new ArrayList<CompositeNode>();

    for (IResourceDescription resourceDescription : resourceDescriptions
    .getAllResourceDescriptions()) {
    Iterable<IReferenceDescription> matchingReferenceDescriptors = Iterables
    .filter(resourceDescription.getReferenceDescriptions(),
    new Predicate<IReferenceDescription>() {
    public boolean apply(IReferenceDescription input) {
    return eObjectDescription
    .getEObjectURI()
    .equals(input.getTargetEObjectUri());
    }
    });
    for (IReferenceDescription matchingReferenceDescription : matchingReferenceDescriptors) {
    CompositeNode node = editor.getDocument().readOnly(
    new URIFragmentResolver(matchingReferenceDescription
    .getSourceEObjectUri().fragment()));
    references.add(node);
    }
    }
    return references;
    }

    private IFile getProjectFile(String filename) {
    IWorkspace ws = ResourcesPlugin.getWorkspace();
    IWorkspaceRoot root = ws.getRoot();
    IProject project = root.getProject();

    IFile file = null;
    if (project == null) {
    IPath path = ws.getRoot().findMember(filename).getFullPath();
    file = ws.getRoot().getFile(path);
    } else {
    file = project.getFile(filename);
    }

    return file;
    }

    }


    The handler called from the command "RenameRefactoringHandler.java":


    package mysomething.refactoring.rename;

    import org.eclipse.core.commands.AbstractHandler;
    import org.eclipse.core.commands.ExecutionEvent;
    import org.eclipse.core.commands.ExecutionException;
    import org.eclipse.jface.dialogs.MessageDialog;
    import org.eclipse.jface.text.ITextSelection;
    import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
    import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.ui.handlers.HandlerUtil;
    import org.eclipse.xtext.parsetree.CompositeNode;
    import org.eclipse.xtext.resource.IEObjectDescription;
    import org.eclipse.xtext.resource.IResourceDescriptions;
    import org.eclipse.xtext.ui.core.editor.XtextEditor;
    import mysomething.Rule;
    import mysomething.utils.EObjectResolver;
    import mysomething.utils.URIFragmentResolver;

    import com.google.inject.Inject;

    public class RenameRefactoringHandler extends AbstractHandler {

    @Inject
    private IResourceDescriptions resourceDescriptions;

    @Override
    public Object execute(ExecutionEvent event) throws ExecutionException {
    try {
    String currentName = "";

    XtextEditor editor = (XtextEditor) HandlerUtil
    .getActiveEditor(event);

    final ITextSelection selection = (ITextSelection) editor
    .getSelectionProvider().getSelection();

    final IEObjectDescription eObjectDescription = editor
    .getDocument()
    .readOnly(
    new EObjectResolver(selection, resourceDescriptions));

    CompositeNode o = editor.getDocument().readOnly(
    new URIFragmentResolver(eObjectDescription.getEObjectURI()
    .fragment()));

    if (o.getElement() instanceof Rule) {
    Rule r = (Rule) o.getElement();
    currentName = r.getName();
    }

    RenameProcessor processor = new RenameProcessor(editor,
    resourceDescriptions);
    RenameRefactoring refactoring = new RenameRefactoring(processor);

    RenameRefactoringWizard wizard = new RenameRefactoringWizard(
    refactoring, RefactoringWizard.WIZARD_BASED_USER_INTERFACE);
    wizard.setRenameText(currentName);

    RefactoringWizardOpenOperation openOperation = new RefactoringWizardOpenOperation(
    wizard);

    openOperation.run(Display.getCurrent().getActiveShell(),
    "Refactoring not possible!");

    } catch (Exception e) {
    MessageDialog.openInformation(
    Display.getDefault().getActiveShell(),
    "Rename Refactoring",
    "Error while applying refactoring to workbench/wizard: "
    + e.getMessage());
    e.printStackTrace();
    }
    return null;
    }

    }


    and we have the two gui classes "RenameRefactoringWizard.java" and "RenamePageComposite.java":

    package mysomething.refactoring.rename;

    import org.eclipse.jface.wizard.IWizardPage;
    import org.eclipse.ltk.core.refactoring.Refactoring;
    import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
    import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
    import org.eclipse.swt.widgets.Composite;

    public class RenameRefactoringWizard extends RefactoringWizard {

    private RenameInputWizardPage wizardPage;
    private String renameText = "";

    public RenameRefactoringWizard(Refactoring refactoring, int flags) {
    super(refactoring, flags);
    }

    @Override
    protected void addUserInputPages() {
    wizardPage = new RenameInputWizardPage("Refactoring");
    wizardPage.setRenameText(renameText);
    addPage(wizardPage);
    }

    public void setRenameText(String s) {
    renameText = s;
    if (wizardPage != null)
    wizardPage.setRenameText(s);
    }

    static class RenameInputWizardPage extends UserInputWizardPage {

    private RenamePageComposite composite;
    private String renameText;

    public RenameInputWizardPage(String name) {
    super(name);
    setTitle("Rename Refactoring");
    setDescription("Automated Refactoring to rename rule names, rule references etc."
    + " with the possibility to automatically update references");
    }

    public void createControl(Composite parent) {
    composite = new RenamePageComposite(parent, 0);
    composite.getRenameText().setText(renameText);
    composite.getRenameText().selectAll();
    setControl(composite);
    }

    public String getRenameText() {
    return composite.getRenameText().getText();
    }

    public void setRenameText(String s) {
    renameText = s;
    if (composite != null)
    composite.getRenameText().setText(renameText);
    }

    @Override
    public IWizardPage getNextPage() {
    RenameRefactoring refactoring = (RenameRefactoring) getRefactoring();
    if (refactoring != null) {
    refactoring.setRenameText(getRenameText());
    }
    return super.getNextPage();
    }

    @Override
    protected boolean performFinish() {
    RenameRefactoring refactoring = (RenameRefactoring) getRefactoring();
    if (refactoring != null) {
    refactoring.setRenameText(getRenameText());
    }

    return super.performFinish();
    }
    }

    }



    package mysomething.refactoring.rename;

    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.Label;
    import org.eclipse.swt.widgets.Text;

    public class RenamePageComposite extends Composite {
    private Text renameText;

    public RenamePageComposite(Composite parent, int style) {
    super(parent, style);
    final GridLayout gridLayout = new GridLayout();
    setLayout(gridLayout);

    final Composite composite = new Composite(this, SWT.NONE);
    composite.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING,
    true, false));
    final GridLayout gridLayout_1 = new GridLayout();
    gridLayout_1.numColumns = 2;
    composite.setLayout(gridLayout_1);

    final Label renameLabel = new Label(composite, SWT.NONE);
    renameLabel.setLayoutData(new GridData(GridData.BEGINNING,
    GridData.CENTER, false, true));
    renameLabel.setText("New Name:");

    renameText = new Text(composite, SWT.BORDER);
    renameText.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
    true, true));
    }

    @Override
    public void dispose() {
    super.dispose();
    }

    public Text getRenameText() {
    return renameText;
    }
    }


    Finally, two helper classes that deal with the EObject stuff:


    package mysomething.utils;

    import java.util.Iterator;

    import org.eclipse.emf.common.util.URI;
    import org.eclipse.emf.ecore.EObject;
    import org.eclipse.emf.ecore.util.EcoreUtil;
    import org.eclipse.jface.text.ITextSelection;
    import org.eclipse.xtext.resource.EObjectAtOffsetHelper;
    import org.eclipse.xtext.resource.IEObjectDescription;
    import org.eclipse.xtext.resource.IResourceDescription;
    import org.eclipse.xtext.resource.IResourceDescriptions;
    import org.eclipse.xtext.resource.XtextResource;
    import org.eclipse.xtext.util.concurrent.IUnitOfWork;

    import com.google.common.base.Predicate;
    import com.google.common.collect.Iterables;

    public class EObjectResolver implements
    IUnitOfWork<IEObjectDescription, XtextResource> {
    private final ITextSelection selection;
    private IResourceDescriptions resourceDescriptions;

    public EObjectResolver(ITextSelection selection,
    IResourceDescriptions resourceDescriptions) {
    this.selection = selection;
    this.resourceDescriptions = resourceDescriptions;
    }

    public IEObjectDescription exec(XtextResource state) throws Exception {
    EObject element = EObjectAtOffsetHelper.resolveElementAt(state,
    selection.getOffset(), null);
    if (element != null) {
    final URI eObjectURI = EcoreUtil.getURI(element);
    IResourceDescription resourceDescription = resourceDescriptions
    .getResourceDescription(eObjectURI.trimFragment());
    if (resourceDescription != null) {
    Iterator<IEObjectDescription> eObjectDescriptions = Iterables
    .filter(resourceDescription.getExportedObjects(),
    new Predicate<IEObjectDescription>() {
    public boolean apply(
    IEObjectDescription input) {
    return input.getEObjectURI().equals(
    eObjectURI);
    }
    }).iterator();
    if (eObjectDescriptions.hasNext()) {
    return eObjectDescriptions.next();
    }
    }
    }
    return null;
    }
    }



    package mysomething.utils;

    import org.eclipse.emf.ecore.EObject;
    import org.eclipse.xtext.parsetree.CompositeNode;
    import org.eclipse.xtext.parsetree.NodeAdapter;
    import org.eclipse.xtext.parsetree.NodeUtil;
    import org.eclipse.xtext.resource.XtextResource;
    import org.eclipse.xtext.util.concurrent.IUnitOfWork;

    public class URIFragmentResolver implements
    IUnitOfWork<CompositeNode, XtextResource> {
    private String uriFragment;

    public URIFragmentResolver(String uriFragment) {
    this.uriFragment = uriFragment;
    }

    @Override
    public CompositeNode exec(XtextResource state) throws Exception {
    EObject o = state.getEObject(uriFragment);
    NodeAdapter node = NodeUtil.getNodeAdapter(o);

    return node.getParserNode();

    }
    }

    Samstag, 12. Dezember 2009

    sofortüberweisung.de!?!

    Nanu, ich wollte mir gerade eine Apple Care Garantieverlängerung für mein Macbook holen (eine Geschichte für sich, da man offensichtlich auf Originalboxen bestehen sollte) und habe mich dann entschlossen lieber bei mac*****.de als (hoffentlich) authorisierten Apple Händler einzukaufen. Der Preis ist (verglichen mit dem Appleshop) in Ordnung und es gibt eine Box. Plötzlich komme ich zur Bezahlung und die vorgezogene Bezahlungsmethode ist sofortüberweisung.de. Weniger Versandkosten und keine Anmeldung erforderlich, ausserdem TÜV zertifiziert. Was kann da schon schiefgehen dachte ich mir und wähle sofortüberweisung.de aus.

    Das nächste was passiert hat mich schon arg überrascht. Da wollte die Webseite doch tatsächlich von mir meinen PIN wissen. Leicht verunsichert schmeisse ich meinen Google an und siehe da: Verbraucherzentralen warnen vor sofortüberweisung.de und der Paynet AG. Es soll wohl klar gegen die AGBs der Banken verstossen PINs und TANs an Dritte weiterzugeben. Und sowas zertifiziert der TÜV? Zudem sagen ja meines Wissens die neuen Geschäftsbedingungen der Banken, die vor einem Monat oder so in Kraft getreten sind noch einmal glarklar, dass der Kunde selbst für Schäden haftet, wenn er sorglos mit Pins und Tans umgeht.

    Ich habe dem betroffenen Laden (der sicherlich zu den bekannteren Deutschen Apple Online Händlern zählt) empfohlen doch noch einmal über seine präferrierte Zahlungsmethode nachzudenken und darum gebeten die Bezahlung in eine andere Methode umzuwandeln, da ich per sofortüberweisung.de nicht bezahlen werde. Etwas schockiert bin ich dennoch davon, dass es überhaupt solch zweifelhafte Bezahlsysteme gibt (und sich offensichtlich über Jahre halten), die einen AGB Bruch der Bank einfordern.

    Dienstag, 20. Oktober 2009

    Eclipse RCP: no application id found...

    The one mistake i do again and again when separating the branding of an Eclipse RCP app into its own branding plugin is that i forget to include the branding plugin itself in the product definition. Its not really that hard to find the problem if you read the exception correctly, but this little mistake is just too easy to make and nevertheless hard to figure out, because the missing branding plugin in the product definition is never the problem that you expect. Hopefully, the Eclipse guys will add a check at some point whether the plugin that contains the .product file is itself included as a plugin dependency :-)

    Dienstag, 22. September 2009

    Subethaedit Promela Mode

    I have revised and fixed the Promela mode from the Subethaedit website (written by Ingmar J. Stein) a while back. Somehow my submission to the website probably got lost and i didn't follow up on it. Anyway, i revised it once again and you can download it directly from here. In a nutshell, this is what happened to the mode since i started changing the mode from the website:
    • Updated keywords.
    • Fixed a bug the prevent the keywords from being colored correctly.
    • Integrated Applescripts for syntax check and startup of a modified Xspin version.
    • Code folding.
    The bundled Xspin version is a modified version of the latest Xspin 5.2 version. In a nutshell, the xspin version disables any kind of file operation (since you should do that with Subethaedit) and reloads the promela file on any operation. That way, you can use Xspin as a frontend for Spin without fear to break anything and Subethaedit for editing.

    Preliminaries:
    • The promela binary must be placed in /usr/local/bin, i.e., /usr/local/bin/spin. Otherwise, it won't work. See an earlier blog post with a few comments how to compile Spin on MacOS.
    • For Xspin to work, you need Tcl/TK. The versions i use are Tl 8.4.19 and Tk 8.4.19. I can't say whether it will work for different versions. I know i had trouble with more recent versions once.
    The whole thing hasn't been tested extensively, but it works for me and at least for me it works better than the mode on the Subethaedit website. Enjoy!

    Freitag, 18. September 2009

    Integer Programming for Finding Good Groups in Teaching

    So, in a few weeks we are offering the Extreme Programming Lab again. This time we have 20 participants. Last year, we had a few (though not huge) problems, because the groups weren't assigned very evenly. We typically work with two groups who each realize a project in XP style. I got to admit, this uneven assignment was my fault. Back then, I assigned the persons randomly and shifted them them a little according to what i thought i knew about their capabilities.

    This year, i decided to go a different route. For the lab application, i specifically asked for specific capabilities and what the participants thought how good they were at them. According to their statements, i classified each statement to points between 0 and 2. With 0 meaning "little knowledge", 1 meaning "normal knowledge" and 2 meaning "good knowledge". I collected a total of 10 different capabilities. So the question now is, how do i find good groups. My optimal groups would be where every capability is covered by the same degree of points. Moving the participants around in Excel to find a good solution is obviously pretty tedious. After all there are quite a lot of different combinations for those two groups.

    A few years back, i heard a lecture about traffic planning and learnt about integer programming. After some thinking, i came to the conclusion that this is pretty much the same stuff and that integer programming would be the right tool to solve this problem. Therefore, i downloaded the student version of Xpress-IVT as i remembered that i liked Mosel a lot back then. I wasn't wrong. A few hours later (geeeze, you can't write your phd thesis all the time!), i had a working Mosel integer program that in fact solved my little problem for finding optimal groups with evenly distributed knowledge. Maybe someone enjoys this as much as i did. So here it is (Names have been anonymized of course):


    model "Participants Assignment to Groups"
    uses "mmxprs","mmquad","mmive";

    declarations
    PERSONS = 1..20
    GROUPS = 1..2
    SKILL_DIMENSIONS = 1..10
    SKILLS: ARRAY(SKILL_DIMENSIONS,PERSONS) of integer
    SKILL_SUMS: ARRAY(SKILL_DIMENSIONS) of integer
    PERSON_NAMES: ARRAY(PERSONS) of string
    SKILL_NAMES: ARRAY(SKILL_DIMENSIONS) of string
    allowed_deviation = 1

    assign: ARRAY(PERSONS,GROUPS) of mpvar
    end-declarations

    initializations from "initdata.dat"
    SKILL_NAMES
    PERSON_NAMES
    SKILLS
    end-initializations

    groupCount := getsize(GROUPS);
    personCount := getsize(PERSONS);

    writeln("Number of groups: ", groupCount);
    writeln;

    forall(d in SKILL_DIMENSIONS) do
    SKILL_SUMS(d) := 0;
    forall(p in PERSONS) do
    SKILL_SUMS(d) += SKILLS(d,p);
    end-do
    end-do

    forall(d in SKILL_DIMENSIONS) do
    writeln("Skill sum for ", SKILL_NAMES(d),": ",SKILL_SUMS(d), " - average per group: ", SKILL_SUMS(d)/groupCount)
    end-do

    GoodGroups := sum(d in SKILL_DIMENSIONS, p in PERSONS, g in GROUPS) SKILLS(d,p)*assign(p,g)

    forall(p in PERSONS) sum(g in GROUPS) assign(p,g) = 1 ! every person is in one group only

    forall(g in GROUPS) sum(p in PERSONS) assign(p,g) = personCount / groupCount !groupCount ! every group has a maximum of groupCount persons

    forall(d in SKILL_DIMENSIONS) forall(g in GROUPS) sum(p in PERSONS) SKILLS(d,p)*assign(p,g) >= SKILL_SUMS(d)/groupCount - allowed_deviation

    forall(d in SKILL_DIMENSIONS) forall(g in GROUPS) sum(p in PERSONS) SKILLS(d,p)*assign(p,g) <= SKILL_SUMS(d)/g


    The data file looks something like this:


    PERSON_NAMES: ["Person 1",
    ...
    "Person 20"]

    SKILL_NAMES: ["Eclipse",
    "DB/SQL",
    "SVN",
    "UML",
    "Design Patterns",
    "Refactoring",
    "Testing",
    "GUI",
    "Web",
    "Java"]

    SKILLS: [1,0,0,1,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,
    2,2,2,0,1,2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,
    ...
    0,1,2,1,1,2,2,2,1,1,2,1,1,1,1,1,1,1,1,2]


    I hope there is nothing wrong with this little Mosel program. I have to say that i really enjoy optimization every time there is reason to use it. You don't understand what i'm doing here? Just learn a little about linear optimization and integer programming. This is great fun!

    Freitag, 11. September 2009

    ANTLR 3 Java Promela Parser

    I just made a first version of my Java Promela parser (the input language of the Spin model checker) available. Grab it while its hot ;-) Hopefully, it will be integrated into the Spin Eclipse Plugin for on-the-fly syntax checking.

    Next step would be to transfer this stuff to Xtext and design a proper Promela metamodel and somehow implement a pretty printer for Promela which is needed badly. I'm not sure when i have time to do that though. Does anyone have clever ideas how to pretty print a C preprocessed language? You would have to preprocess the Promela files, pretty print them and then reverse the preprocessing somehow. This sounds kind of tricky to me...

    Donnerstag, 10. September 2009

    O2 UMTS Prepaid Surfstick (ICON 210) und Snow Leopard - Beim Kauf schon veraltet!

    Am 31.8. bin ich in den O2 Laden gelaufen, um mir ein Backup-Internet für meine Geschäftsreisen zu besorgen. 60 EUR später festgestellt, das dieser mit Snow Leopard, am 28.8. veröffentlicht inkompatibel ist. Nagut, nicht so schlimm - ich habe ja noch einen Ersatzstick von Novatel MC950D, der nach einem Treiberupdate von einer versteckten MacOS Website von Novatel auch einwandfrei seinen Dienst verrichtete.

    Heute habe ich dann mal bei O2 angerufen und nachgefragt, was denn mit einem Treiberupdate für den ICON 210 UMTS Stick sei. Sie hätten ja jetzt genügend Zeit gehabt einen neuen Treiber zu beschaffen. Antwort: für den ICON 210 wird es leider kein Update mehr geben. Es wird bald einen neuen Stick geben. Den kriege ich natürlich dann nicht für Lau. Ich habe den netten Herren darauf hingewiesen, dass Snow Leopard schon raus war als ich mir das Prepaid Angebot geholt habe und nicht darauf hingewiesen wurde, dass der Stick mit aktuellen Betriebssystemen nicht funktionieren wird.

    Nunja, das gibt eine schriftliche Beschwerde. Ich weiss echt nicht was das Problem mit den UMTS Sticks und dem Support dafür ist - man hat damit fast immer nur Ärger. Da lobe ich mir ja fast meine versteckte Novatel Treiberseite (die man allerdings auch erst nach stundenlanger Netzrecherche findet). Und O2? Was für ein Saftladen! Servicewüste Deutschland halt - in anderen Ländern hätten die sich jetzt den Kopf darüber zerbrochen wie sie mir helfen können. Darauf wartet man hier lange...

    Mittwoch, 9. September 2009

    Compiling Spin on the Mac

    This is primarily a reminder for myself :-) Edit the makefile, add to the CFLAGS "-DMAC". Then, edit main.c. Find the line:

    #define CPP "/lib/cpp" /* classic Unix systems */

    change it to

    #define CPP "/usr/bin/cpp" /* classic Unix systems */

    This is supposed to work via -DCPP=/usr/bin/cpp, but somehow it doesn't.

    Sonntag, 16. August 2009

    Why the Windows 7 dock is awkward for the OS X user

    So I have Windows 7 running since it came out for the academia on Friday. As a Mac user, I was quite interested to see what the new dock in Windows 7 would be like as it is obviously inspired by the OS X dock - no question about that. However, Microsoft somehow didn't manage to carry over the way the OS X dock is used. The result is unfortunately something slightly awkward. Nothing particulary bad or so, but just awkward if you have used the OS X dock before. Here it is:
    1. I keep on accidentally closing my apps. Why? Because I click the top-right "X". Yes, it used to be Windows behavior that the "X" closes an application. But now that we have the OS X-like dock, it becomes strange. In OS X, the X means that the Window is closed, but the app stays open in the dock. Not so in Windows, you have to minimize the application if it should stay in the dock. Sounds logical, but it isn't for the Mac user. While Microsoft adopted the dock idea, they didn't adopt the window management idea of OS X. I'm not quite sure yet whether this is just inconsistent or just unaccustomed for the Mac user. I will need a while to get used to that. Hopefully, someone will find a way to remap the upper-right "X" to minimize ;-)
    2. I was about to write that you can't close applications from the dock. Again this is something highly confusing what Microsoft did here. When you right-click the dock icon of an open app, in German you the choice "Fenster schliessen" or "Alle Fenster schliessen" which basically means "Close windows" and "Close all windows". I always expected this to mean that the Windows are minimized back to the dock, but no, it in fact means that the apps will be closed. Why don't you just write "Close application" in there rather than confusing the user with something happening to the windows? Oh yes, there might be an application that actually remaps the "X". I think this clearly demonstrates how inconsistent the window management in Windows is, i.e., closing Windows can mean anything from closing an application to minimizing of all windows.
    Another thing is the interplay between the apps that use the systray. Quite often, there are applications that minimized to the systray when you close the window (also with the "X" button). Not if you have such an application now (like Pidgin or Thunderbird with the systray addon), you minimize the window and it is put back into the systray just as expected. However, the dock icon now marks the application as "not running". This is highly confusing. The mutual behavior between the dock and the systray is really everything but consistent with the new dock. As a result, i deatived the systray feature in most of my apps.

    By the way, i highly dislike the window when you right-click a dock icon - it seems somehow temporary and unpolished. At first, i thought the new Windows 7 dock was a good idea. But it turns out, it causes more problems for me than it solves. Enough Windows 7 blasphemy - for now.