11 Feb 2009

RSync for windows, mac and linux: Unison ?

Lately I re-installed all my home computers, that means backuping everything to DVD(s).
It's always a really painfull operation, there are differents files and differents folders structure across computers /os (windows, ubuntu...). Some files are the same, some where deleted but not everywhere etc...
So usually I spend almost a week-end cleanup the mess accumulated over 2 or 3 years.

I tried to use subversion to backup files so that I could use associate tools to ease the job. It was a failure for many reasons:
- Using svn add/move everytime you do something with a word, pdf etc... is painfull
- That means synchronising with some kind of server and I don't want to have a running computer all day long at home
- I don't need versions on those documents
- You need a big storage place (+ extra svn info) for the repository

For the sotrage problem I bought a 1To USB external drive! Should be fix now :)

For the rest, I think rsync is better for what I need!
Unfortunatly there is no such thing for windows unless you use cygwin... I'm not really found of cygwin (it's better than nothing but...)

I just found Unison, an implementation of rsync but available on multiple plateforms. Windows, Mac, Linux clients.
I did some tests under windows and it seems to work :)
I only used the client line since the graphical client need Gtk+ (I don't want to install it just for that) and it will be ugly (as usual with gtk).

I need to test the linux client and I should be ready to go...

6 Feb 2009

Jetty - change default java.io.tmpdir value and override web.xml parameters

Jetty is really nice, amongst the amazing things you can do some of my favorites are:
  • Change java.io.tmpdir default value
  • override params define in the web.xml embedded in a war file


java.io.tmpdir


<?xml version="1.0"  encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="contextPath">/test</Set>
...
<!-- change java.io.tmpdir default value -->
<Call class="java.lang.System" name="setProperty">
<Arg>java.io.tmpdir</Arg>
<Arg>/some/where</Arg>
</Call>
</Configure>

Change default values in web.xml


<?xml version="1.0"  encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="contextPath">/test</Set>
...
<Set name="overrideDescriptor">
<SystemProperty name="jetty.home"
default="."/>/contexts/test.d/override-web.xml</Set>
</Configure>

Create an 'override-web.xml'
<?xml version="1.0"  encoding="UTF-8"?>
<web-app ...>
<!-- Add or override context init parameter -->
<context-param>
<param-name>my.param/param-name>
<param-value>on</param-value>
</context-param>
</web-app>

29 Jan 2009

Postgresql and the trigger of death

Description of the problem:
I have a table with 2 columns date_acq and time_acq as text

CREATE TABLE "shapefiles" (gid serial PRIMARY KEY,
"date_acq varchar(10),
"time_acq" varchar(8));


I want a colum with a datetime time with the informations from date_acq and time_acq so that I can use the < and > sql operator.


I added a new column datetime_acq of type datetime and a trigger getting the information from date_acq and time_acq and putting them into the new column.
The trick is that the date is express in french format that is DD/MM/YYYY.


After learning and fighting with postgres stored procedure language I finally got a nice looking solution:

BEGIN;
ALTER TABLE shapefiles DROP COLUMN datetime_acq;
ALTER TABLE shapefiles ADD COLUMN datetime_acq timestamp with time zone;
COMMIT;

DROP FUNCTION IF EXISTS datetime_acq_timestamp() CASCADE;
CREATE FUNCTION datetime_acq_timestamp() RETURNS trigger AS $datetime_acq_timestamp$
DECLARE
temp_date text;
french_pattern text := 'DD/MM/YYYY';
BEGIN
-- Check that date_acq and time_acq are given
IF NEW.date_acq IS NULL THEN
RAISE EXCEPTION 'date_acq cannot be null';
END IF;
IF NEW.time_acq IS NULL THEN
RAISE EXCEPTION 'time_acq cannot be null';
END IF;

-- Updating datetime_acq column
SELECT TO_CHAR(TO_DATE(NEW.date_acq,french_pattern), 'YYYY-MM-DD') into temp_date;
NEW.datetime_acq := temp_date || ' ' || NEW.time_acq;
RETURN NEW;
END;
$datetime_acq_timestamp$ LANGUAGE plpgsql;

CREATE TRIGGER datetime_acq_trigger BEFORE INSERT OR UPDATE ON shapefiles
FOR EACH ROW EXECUTE PROCEDURE datetime_acq_timestamp();

"Et voilĂ !" Now I have a nice column with valuable informations:

XSD schema validation for XSL and auto-completion in eclipse (second edition)

In Jan 8, 2006 I made a post about making xsl autocompletion work under eclipse... but I was in a hurry so the old post is not top quality ;)

Let fix it and make it a first class citizen :)

First you can download 2 already pre-configured empty files:

  • test-default-namespace.xsl

    <?xml version="1.0" encoding="UTF-8"?>
    <stylesheet xmlns="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemalocation="http://www.w3.org/1999/XSL/Transform
    http://www.w3.org/2005/02/schema-for-xslt20.xsd"
    version="2.0">

    </stylesheet>


  • test-not-default-namespace.xsl

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemalocation="http://www.w3.org/1999/XSL/Transform
    http://www.w3.org/2005/02/schema-for-xslt20.xsd"
    version="2.0">

    </xsl:stylesheet>


Now you need to setup eclipse, Go to Windows > Preferences then XML > XML Catalogs.
Copy the exact same informations that the screen capture below!!




Validate your the xsl with Right click on the file in eclispe > Validate

When you hit Ctrl+Space, it should work now!
You shouldn't have any error or warning, especially the warning telling you that eclipse couldn't find the dtd or xml schema for xsl namespace!

Gotchas:
  • Especially if you internet connection is slow, you need to wait a few seconds after opening the xsl before hitting Ctrl+Space because eclipse is downloading the file from http://www.w3.org/2005/02/schema-for-xslt20.xsd
  • I don't know why because I have to close/reopen the eclipse editor for changes to take place

Technorati tags: xsl eclipse

Fomatting messages

I always found formatting Strings was painful in Java. Especially since I learn Ruby where you can do:
some = 'foobar'
my_string = "Here are #{some} value"

In Java, a basic example would be:
String searchPolygon = "POLYGON((" + lowerLeft + ", " + 
lowerRight + ", " + upperRight + ", "
+ upperLeft + ", " + lowerLeft + "))";

If you have too many parameters or you are looking for more efficiency, you can do something like (you can use StringBuffer instead of StringBuilder see javadoc):
StringBuilder searchPolygon = new StringBuilder();
searchPolygon.append("POLYGON((");
searchPolygon.append(lowerLeft);
searchPolygon.append(", ");
searchPolygon.append(lowerRight);
searchPolygon.append(", ");
searchPolygon.append(upperRight);
searchPolygon.append(", ");
searchPolygon.append(upperLeft);
searchPolygon.append(", ");
searchPolygon.append(lowerLeft);
searchPolygon.append("))");
searchPolygon.toString();

But still, it's ugly :(


Or you can use MessageFormat wich make the code more much readable in my opinion ;)

MessageFormat polygonFormatter =
new MessageFormat("POLYGON(({0}, {1}, {2}, {3}, {4}))");
Object[] values = new Object[] {
lowerLeft, lowerRight, upperRight, upperLeft, lowerLeft };
String searchPolygon = polygonFormatter.format(values);


It could have even be better if we could have use a map with key/value instead of indexes... but I didn't found anyting in the java language itself that does this :(

3 Dec 2008

Insert Polygon into Postgis

I was trying to insert a polygon (I think it's the same as a bbox but not sure yet) into a postgis table. But I only found scaterred examples where the columns declaration was missing... So here's a concret example.
The SQL:

SELECT AddGeometryColumn( 'my_table', 'geo_bbox', 4326, 'POLYGON', 2);
UPDATE my_table
SET geo_bbox=GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))',4326)
WHERE id='my_pk';

Where '4326' is the standard/normal/usual coordinnates system: longitude/latitude. You can do the following to get more info about '4326':
select * from spatial_ref_sys where SRID=4326;


To check if everything is working you can do:

SELECT ST_Contains(geo_bbox, GeomFromText('POINT(2 2)',4326))
FROM my_table
WHERE clef='my_pk';

It should return 't' for 'true'.

Errors I've bumped into and their "gotchas":
  • parse error - invalid geometry
    UPDATE my_table 
    SET geo_bbox=GeomFromText('POLYGON(0 0,4 0,4 4,0 4,0 0)',4326)
    WHERE clef='my_pk';
    ERROR: parse error - invalid geometry
    CONTEXT: SQL function "geomfromtext" statement 1

    You forget the double '((' and '))'. There is a double '((' because Polygon can be describe like this: POLYGON((first_shape), (second_shape))
  • geometry contains non-closed rings
    UPDATE my_table 
    SET geo_bbox=GeomFromText('POLYGON((0 0,4 0,4 4,0 4))',4326)
    WHERE clef='my_pk';
    ERROR: geometry contains non-closed rings
    CONTEXT: SQL function "geomfromtext" statement 1
    You forget the last coordinates, you need to repeate the first point twice:
    POLYGON((down_left, down_right, up_right, up_left, down_left))
  • geometry contains non-closed rings
    UPDATE my_table 
    SET geo_bbox=GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 10))',4326)
    WHERE clef='my_pk';
    ERROR: geometry contains non-closed rings
    CONTEXT: SQL function "geomfromtext" statement 1
    That's because the finishing point (0,10) is not the same as the starting point (0,0)
  • other: invalid geometry
    I also got an other way to get an "invalid geometry" but I don't remember how to reproduce it... postgis does some validation if your coordinates are not valid.


Postgis official documentation: Creating object syntaxe

Technorati tags:

2 Dec 2008

ohloh la!

I just discovered ohloh.net after reading Marting Fowler latest post.

Ohloh display informations about open source projects: commits, timelines, contributors, languages etc...

Amazing how they managed to extract valuable informations for internet/svn/projects and how they presented it in a meaningful way!

I had lots of fun finding people I know:

Or project I've worked with:

This can help see if a project is under active development or not and who is really working on, not just claiming to be a contributor ;)

27 Nov 2008

Insert big data chunk into MySQL

Inserting 370 000 records in a mysql table was taking ages!
Found this little trick:
LOAD DATA CONCURRENT LOCAL INFILE 'C:\\my\\path\\to\\folder\\records.sql' INTO TABLE FOO;

Useful under Windows and MySQLQueryBrowser ;)

MySQL funny command line option

While searching for help for mysql ubuntu command line tool:

$ mysql --help
Usage: mysql [OPTIONS] [database]
-?, --help Display this help and exit.
...
-U, --i-am-a-dummy Synonym for option --safe-updates, -U.
...

19 Nov 2008

Flag a blog post as deprecated

While looking for some info on capistrano I stumbled on this post: "Ant sucks for FTP deployment - What alternatives do we have?".

The funny thing is the deprecated notice:


I often use @deprecated for the code but I never though of using it for my old blog posts... good idea :)

And it's also a good way to always keep url even if they display wrong or inaccurate info, just like describe in this w3c document "Cool URIs don't change."