Monday, July 28, 2008

Ruby cp_r caveat

The ruby fileutil function cp_r, copies a directory, all of its files and subdirectories to a target location.  This is very useful when you are trying to sync 2 directories.  However, by default it will copy the directory as a subdirectory of the supplied target directory.  So:

cp_r "c:\\fly", "c:\\soup"

would give you:


Now you have a fly in your soup.  This is a serious problem.  What if you were trying to sync your stick and donkey folders?

To get around this, just stick a period at the end of the the original directory path.  Like so:

cr_r "c:\\fly\\.", "c:\\soup"

Friday, July 18, 2008

A tale of two documentations

From time to time I find myself needing to integrate our system with some external vendor, and that usually means writing an XSL transform.  Last week I had 2 completely different experiences dealing with documentation from a couple of vendors.  Let's compare, shall we?

Company #1:

Company #1 is a large internet video distribution company, which "empowers content owners... to reach their audiences directly through the internet."  And they are very good at what they do.  They have probably fed you a video through some web site and you don't even know it.  So when it came time to generate an xslt to integrate with their system, I sat down and read the 4 separate documents that describe how to generate the xml manifest.  For the next few days, I played email tag with their support team as I fixed one issue only to unveil another.  It turned out that their documentation had a few errors.  You know, little things like incorrect tag names, required fields that weren't specified as required, and the fact that their xml parser is case sensitive.   That last one really steamed me.  I have since used the documentation as firewood to fend off the chill that came over me after excluding a distribution region by using a tag named "allow" (no attributes on this tag).

Company #2:

On the opposite end of the spectrum is company #2.  Its a small, very specialized, service provider with a single developer currently dedicated to this particular project.  Instead of getting a word or pdf document describing the xml creation process, I was given a highly commented DTD document.  And, surprise, this integration worked the first time without errors. 

I've conversed with several of my colleagues about this and most of them fail to see the awesomeness of this approach.  So, for those of you who missed it, here's why it is so awesome.  Not only was the documentation completely correct, it couldn't have been incorrect.  By passing me their DTD, they were saying "Here is the code that we use to validate your response.  If it validates for you, it will validate for us as well."  In this instance the code itself was enough.  They didn't even have to send an example xml file.  XmlSpy generated one in less than a second. 

I also feel that the comments left directly in the code, in this case the DTD, are a much clearer reflection of the author's intent.  This is the author spilling out his thought process, not just some dud that's been told to document a process by Friday. 

This experience just validates my belief that large external documents are slowly going the way of the dodo.  I've felt this way for a while now.  I'm a big fan of less documentation that is more useful.  Think about it.  End user's don't want to read a manual anymore.  They've come to expect inline help and most are even trained to look for tooltips. 

Song of the day:
State of the Union - David Ford - I Sincerely Apologize for All the Trouble I've Caused

Thursday, July 17, 2008

Uppercase in XSLT

XPATH doesn't have a built in ToUpper() or ToLower() function.  However, you can use the translate function to switch cases.  Here's an example that changes the word "Upper" to all upper case.

<xsl:variable name="text" select="'Upper'" />
<xsl:value-of select="translate($text, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

If you want to go the other way and lowercase your string, just flip-flop the alphabet strings.

<xsl:variable name="text" select="'Upper'" />
<xsl:value-of select="translate($text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'" />

Song of the day:
Twilight Zone(Live) - Golden Earring - The Naked Truth

Tuesday, July 15, 2008

Subversion Video

I came across this getting started with subversion video by Dan Wahlin. It's pretty good and would have saved me hours if I had know about it when I got started.  Dan does a good job explaining some of subversion's quirks and how to get around them.

Song of the day:
Africa(Toto Cover) - Pyogenesis - Mono... or Will It Ever Be The Way It Used To Be

Monday, July 14, 2008

C# Succ

I have a project which requires me to generate multiple artifacts with sequential names.  No sweat, right?  Just stick a number on the end of the name and increment it.  Well, what if your users prefer letters to numbers? 

Ruby's string.succ function returns the successor to the string by incrementing characters starting from the rightmost alphanumeric character.  It's a shame that C# doesn't have this built in. 

Here's my stab at recreating the Ruby succ function in C#.  It's not as robust as the ruby version, as it only handles letters, but it is a start and it meets my needs for now.

public static string Succ(string value)
List<string> alphabet = new List<string>(" ,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z".Split(",".ToCharArray()));
char[] values = (" " + value).ToUpper().ToCharArray();
bool addone = true;

for(int i = values.Length - 1; i > -1; i--)
if (addone)
if (values[i] != 'Z')
values[i] = char.Parse(alphabet[alphabet.IndexOf(values[i].ToString()) + 1]);
addone = false;
values[i] = 'A';

return new string(values).Trim();

Here's some sample output:

  • Succ("R") => "S"

  • Succ("Z") => "AA"

  • Succ("ZAZ") => "ZBA"

Song of the day:

A Moment of Clarity - Therapy? - Infernal Love