Thursday, June 28, 2007

I want my feature request implemented yesterday!

"What do you get when you put together a bunch of passionate developers and a code freeze policy due to the end of a release?" This is probably a good start for a Dilbert cartoon. Certainly Scott Adams' answer would be brazilian times funnier than mine, which is "crazy people implementing the cool things they want regardless of how beautiful the day is outside".

The "cool thing" I worked on yesterday was to leverage the pattern filter widget you see on Eclipse's New Project Wizard to some EMF dialogs. After some digging I was able to get the results I was looking for by simply using new FilteredTree(...).getViewer() instead of new TreeViewer(...). BTW, I would recommend reading the PatternFilter's Javadoc if you are considering doing the same in your code.

Everything was going smooth up to the moment that I've opened a subclass of org.eclipse.ui.dialogs.ElementTreeSelectionDialog. I couldn't believe what I was seeing: there was no way to replace the TreeViewer used by this class. Profoundly disappointed, I began to write a feature request for the UI team. As I was doing it, I thought that I would be a much better Eclipse citizen by providing a patch instead of simply describing what to do. So I checked out the "org.eclipse.ui.workbench" bundle, opened ElementTreeSelectionDialog, and added a new protected method that instantiates the TreeViewer. Before changing the line of code that would use my new method, I looked around to see how the Javadocs on the file are written. To my surprise I discovered this new method: ElementTreeSelectionDialog.doCreateTreeViewer(Composite, int). After blinking my eyes for a few seconds I realize that the method I need is already available in Eclipse 3.4. Amazing!

Kudos to the UI team.

Tuesday, June 26, 2007

EMF tips and tricks: Don't save if it hasn't changed.

For a while I have been thinking about writing some EMF tips that may not be known by most of the users. What keeps me from doing it is the lack of inspiration to come up with a nice introduction and to explain the rationale behind a design. This is probably silly though. I am sure I would be way more useful if I simply focus on showing the "what" and "how", leaving the long discussions for the cases when someone is actually interested ;-)

So here we go...

We've added a few new options to the EMF Resource in EMF 2.3 (the one available in Europa). One of them is Resource.OPTION_SAVE_ONLY_IF_CHANGED. When this option is used, the save method writes out the bytes of the serialized objects only if these bytes are different from the existing persisted form of the resource. Behind the scenes, the objects in the resource are serialized to either a temporary file or memory buffer and then compared with the bytes read from the URI pointed to by the resource. Clearly this slows down the save operation, but it may be useful when, for example, the resource serializes to a file that is versioned by CVS, hence avoiding "zero delta" changes.

This snippet shows how to use this option:

Map<Object, Object> saveOptions = new HashMap<Object, Object>();
saveOptions.put(
Resource.OPTION_SAVE_ONLY_IF_CHANGED,
Resource.OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER);
resource.save(saveOptions);

Using OPTION_SAVE_ONLY_IF_CHANGED_FILE_BUFFER instead of OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER would serialize the objects to a temporary file instead of using a buffer in memory. This subtle difference is important when dealing with big resources.

An experienced EMF user may be asking how this relates to the Resource.setTrackingModification(boolean) method and to the "dirty" state of the editor generated by EMF. The main difference here is that the new option applies to the actual bytes of the serialized resource while the other two approaches are related to the state of the objects in memory. For example, the new option doesn't change the serialized resource when a "dummy" modification is made to an object (such as setting an attribute to its current value), but would do it if the serialization format changes (which could be caused by using a different value for the XMLResource.OPTION_LINE_WIDTH option, for instance). The other two approaches do the exact opposite in these examples.

Friday, June 8, 2007

From iterator-loop to foreach-loop with one regex.

Probably the most important feature we've worked on this release was to add Java 5.0 support to EMF. We've learned a lot during the process and actually had some fun trying to make sense out of Generics and Annotations. Of course there were also some very annoying tasks, such as converting Java 1.4 "Iterator loops" into the new "foreach loop" style. For example, this snippet

for (Iterator i = Collections.singleton(new Integer(1)).iterator(); i.hasNext();)
{
Integer integer = (Integer)i.next();
System.out.println(integer);
}

should look like this after the modifications
for (Integer integer : Collections.singleton(new Integer(1)))
{
System.out.println(integer);
}

Unfortunately Eclipse's "Source->Clean..." magic action doesn't do a good job here since it doesn't keep the names and types of the "each" variable. At least back in December, I would end up with Object object : instead of Integer integer : for the example above.

Either to boost my productivity or just to exercise the right to be lazy ;-), I've come up with a regular expression that does the conversion for me. It works flawless with Eclipse's Find dialog (ctrl+f):



Here's a clipboard friendly version:
Find:
(for\s*\(\s*)Iterator\s*\w*\s*=(.*)\.iterator\(\).*;\s*(\)\s*\{\s*)(.*)\s*=.*next\(\);\s*

Replace with:
$1$4:$2$3

Monday, June 4, 2007

I can't see the code I blog!

Today I was proudly showing my blog to Dave, a good friend from work. "Proudly" would be the perfect word if it also meant "embarrassed". While I consider myself an illiterate in multiple languages (after 7 years in Canada I haven't learned English yet and my Portuguese is starting to fade away), Dave is my "English hero". Not only he writes really well but also knows all the grammar rules that would explain "why one should use a comma here" for example. A typical case of knowing what to do and how to do it. Anyways, I am digressing...

When I was showing the blog to Dave, he pointed out that the chunks of code I wrote were not been properly displayed on his Windows box. After some digging, we found out that the culprit was the "fixed" font on my CSS. After changing it from

font-family: fixed, courier, courier new, times, times new, times new roman;

to
font-family: courier new, courier, fixed,  times, times new, times new roman;

everything worked just fine.

Perhaps I should show this to Nick, another good friend from work, from whom I've stolen... err... leveraged the CSS customizations.

Friday, June 1, 2007

EMF? O que é EMF?

Geralmente quando leio algo sobre o EMF em Português, acabo aprendendo alguma coisa sobre MyEclipse ou VE. Pelo visto o pessoal ainda não descobriu o poder deste componente, tratando-o apenas como mais um incômodo detalhe de instalação.

O EMF, do qual sou desenvolvedor, pode simplificar drasticamente o desenvolvimento de aplicações Java (a serem rodadas no Eclipse ou não). A partir de uma especificação de um modelo (em XML Schema, por exemplo), com apenas alguns cliques, é possível gerar um editor no Eclipse capaz de criar e manipular instâncias deste modelo. Por trás das câmeras, o editor utiliza outro código Java, também gerado pelo EMF, que implementa as classes definidas no modelo. Em outras palavras, se o modelo diz que uma Biblioteca tem Livros, o EMF vai gerar algo parecido com

public class Biblioteca
{
List<Livro> getLivros();
}

Este código é completamente independente do Eclipse, podendo rodar em qualquer ambiente Java. A propósito, Java 5 é opcional.

O EMF pode fazer muito mais que simplesmente gerar código para classes. Espero ter tempo e, porque não, incentivos em forma de perguntas e encorajamentos, para escrever, em Portuga, algumas dicas.

I've been doing the same thing for over 10 years!

On a recent trip to Brazil, I had the unique opportunity to hear "you are so boring" from some close friends of mine. I like to believe they were talking about the fact that I've been working on "modeling", "code generation", and "development processes" for more than 10 years.

It all started in 93 when I read Rumbaugh's OMT book. Since then objects have been part of my life. I implemented (and sometimes managed) several projects modeled using UML and implemented using Java, C++, VisualBasic, and even Eiffel. Also, as a Rational consultant, my work activities were usually related to sell, demo, and teach Rose (not to forget requirement tools, functional testing tools, and whatever Rational had on its package).

Fast forward to 2007. Where I am now? For 3 years, since Jan 2004, I've been working on the coolest project ever: the Eclipse Modeling Framework (EMF).

Modeling and objects to the bone!

What do I do with my passwords?

Have you noticed the incredible number of services, emails, accounts, logins and identities we have to manage on a daily basis? I am sure you already have a technique to handle your ids and passwords. The one I chose is... keep all my information in a text file.

Of course it is not that simple ;-)

I do have a text file with all my ids and passwords though. I write it in a very human legible format (== no xml). You would read something like this if you got your hands on it

www.pizzapizza.com
marcelop/mypass
marcelop@the.email.I.used.here.com


This file is stored on my server, where I make all the changes, and duplicated on the machines I use. Given the importance of the data (to me at least), I decided that it would be wise to encrypt it. Enters ccrypt. This package is available on both Linux and Windows (through Cygwin), and provides a command line application (ccrypt) to encrypt text files and another (ccdecrypt) to do the opposite operation. It also includes 'ccat' that displays the content of the file after decrypting it in memory.

So how do I put everything together? When I need to add a new entry to the file, I ssh to my server and run cad, defined this way:

alias cad='ccdecrypt ~/personal/ids.txt.cpt &&
vi ~/personal/ids.txt &&
ccrypt ~/personal/ids.txt'


This command (1) decrypts the file 'ids.txt.cpt', (2) opens the plain text file using vi, and, after I am done editing it, (3) encrypts the 'ids.txt' file.

After editing the ids file, I return to the machine I am working on (this has started with an ssh, remember?) and run the psync command defined by the following alias

alias psync='scp -p lh:/home/marcelop/personal/ids* ~/personal'


which copies the file located on my server (the alias stands for "personal sync" and actually copies other files that I only edit on the server). After that, whenever I want to check an specific information, I run this alias on the local machine

alias cad='ccat ~/personal/ids.txt.cpt | grep -i -B 2 -A 5 '


So something like cad pizza would display 2 lines above the "pizzapizza" entry and 5 below. Adding this to the .bashrc

export GREP_OPTIONS='--color=auto'


makes it even better, since the word "pizza" would appear in red.

There you are. Seems like a lot of work, but it is actually quite simple. After using this technique for 2 years, it feels absolutely natural.

PS: 'cad' stands for "cadeado" (locker in Portuguese).

Ubuntu!!!!

I don't really hate Windows. Although it is fun to trash it from time to time, it does have its strengths. That said, long life to the Penguins! After using Debian for a while, Ubuntu has made his way into my Desktop and Thinkpad. The former runs on Dapper LTS (I am planning to upgrade it to Feisty in July) and the latter boots Edgy (and, occasionally, Windows XP).

Why Edgy on the Thinkpad? Feisty just doesn't do it for the lappy. Several annoying problems, going from issues connecting the wireless adapter to 'division by 0' exceptions thrown by Skype and VLC made me choose an earlier version of the distribution. Oh well... In October I can give G* (whatever 7.10 is named) a try.

PS: In my case, the 'division by 0' was happening because the geometry of the screen was not set. Running xrandr did the trick for me.