Monday, March 16, 2009

More IList Extension Methods: Quickselect-ing from an Unsorted List

Continuing my extension method kick and inspired by my extension method to select an item from an unsorted list that bets fits comparison criteria, I decided I wanted to try to implement an extension method to select from the list the kth best fit rather than just the best fit.

I left the best fit methods intact because they achieve worst case O(n) time, but the kth select worst case is O(n log n) because the worst case would quicksort the entire array. I later discovered that the method I implemented is called a quickselect. It's a divide an conquer algorithm based on the partitioning scheme of the quicksort.

Basically, with the quicksort, you pick an item (called the pivot) from the list and then put everything smaller than the pivot on the left and everything larger on the right. Then, you recursively quicksort each side of the pivot.

The quickselect uses the same technique, but rather than quicksorting both sides of the pivot, you quicksort only the side which contains the element you're looking for. Id est, if your pivot ends up at index 5 and you're looking for index 7, then you partition the right side. If the next pivot is index 8, then you partition the left side. You keep doing that until your pivot ends up being the index you're looking for.

Here's what the partition methods look like. There's really not a great reason to make them public, but there's also not a good reason to leave them private.
public static int Partition<T>
(this IList<T> list, Comparison<T> comparison, int left, int right)
{
int i = left;
int j = right;

// pick the pivot point and save it
T pivot = list[left];

// until the indices cross
while (i < j)
{
// move the right pointer left until value < pivot
while (comparison(list[j], pivot) > 0 && i < j) j--;

// move the right value to the left position
// increment left pointer
if (i != j) list[i++] = list[j];

// move the left pointer to the right until value > pivot
while (comparison(list[i], pivot) < 0 && i < j) i++;

// move the left value to the right position
// decrement right pointer
if (i != j) list[j--] = list[i];
}

// put the pivot holder in the left spot
list[i] = pivot;

// return pivot location
return i;
}

public static int Partition<T>(this IList<T> list, Comparison<T> comparison)
{
return list.Partition(comparison, 0, list.Count - 1);
}

public static int Partition<T>(this IList<T> list, IComparer<T> comparer)
{
return list.Partition(new Comparison<T>((x, y) => comparer.Compare(x, y)));
}

public static int Partition<T>(this IList<T> list)
where T : IComparable<T>
{
return list.Partition(new Comparison<T>((x, y) => x.CompareTo(y)));
}
Isolating the partition logic makes it really easy to implement both the quicksort logic and the quickselect logic. In fact, in case you're interested, here's what the quicksort logic looks like:
public static void QuickSort<T>
(this IList<T> list, Comparison<T> comparison, int left, int right)
{
// pivot and get pivot location
int pivot = list.Partition(comparison, left, right);

// if the left index is less than the pivot, sort left side
if (left < pivot) list.QuickSort(comparison, left, pivot - 1);

// if right index is greated than pivot, sort right side
if (right > pivot) list.QuickSort(comparison, pivot + 1, right);
}
The quickselect is basically the same thing, except that you don't quicksort both sides of pivot:
public static T QuickSelect<T>
(this IList<T> list, int k, Comparison<T> comparison, int left, int right)
{
// get pivot position
int pivot = list.Partition(comparison, left, right);

// if pivot is less that k, select from the right part
if (pivot < k) return list.QuickSelect(k, comparison, pivot + 1, right);

// if pivot is greater than k, select from the left side
else if (pivot > k) return list.QuickSelect(k, comparison, left, pivot - 1);

// if equal, return the value
else return list[pivot];
}

public static T QuickSelect<T>(this IList<T> list, int k, Comparison<T> comparison)
{
return list.QuickSelect(k, comparison, 0, list.Count - 1);
}

public static T QuickSelect<T>(this IList<T> list, int k, IComparer<T> comparer)
{
return list.QuickSelect(k, new Comparison<T>((x, y) => comparer.Compare(x, y)));
}

public static T QuickSelect<T>(this IList<T> list, int k)
where T : IComparable<T>
{
return list.QuickSelect(k, new Comparison<T>((x, y) => x.CompareTo(y)));
}

Sunday, March 15, 2009

Revised IList Extension Methods for Selecting Best Fitting Items from an Unsorted List

Several days ago, I started writing articles about extension methods. One of the articles I wrote was about an IList extension method to select the best fitting item out of an unsorted list in O(n) (linear time). I was working on another article about implementing the quicksort and quickselect algorithms as extension methods.

I got pretty tired of having the same logic implemented in multiple places, but I hadn't yet figured out how to refactor it. Well, I did, so this is an update to those methods that keeps most of the work in one place.

I think it's a pretty cool implementation, it still works correctly, and it's still relatively fast. This implementation is also still side-effect free. That's one reason to use it over a sort/select method. If you need to leave your IList unsorted, then you can't sort and select. Also, if you are selecting from items with a custom IComparer, then even if you don't care about side-effects, you're still better off using this method.

On the other hand, if you don't care about the order of your list and your list type can be sorted with the native TrySZSort, then you're better off using Array.Sort() and selecting the last item in the list. However, if it can't be externed to TrySZSort then the .Net implementation of Array.Sort() uses quicksort which is O(n log n) and the selection is O(1). That's less efficient than the O(n) implementation below.
public static T GetBestFit<T>(this IList<T> list, Comparison<T> comparison)
{
if (list == null || list.Count == 0)
throw new ArgumentException("You cannot get the best fit from an empty list!");

T currentFit = list[0];
for (int i = 1; i < list.Count; i++)
if (comparison(currentFit, list[i]) < 0)
currentFit = list[i];

return currentFit;
}

public static T GetBestFit<T>(this IList<T> list, IComparer<T> comparer)
{
return list.GetBestFit(new Comparison<T>((x, y) => comparer.Compare(x, y)));
}

public static T GetBestFit<T>(this IList<T> list)
where T : IComparable<T>
{
return list.GetBestFit(new Comparison<T>((x, y) => x.CompareTo(y)));
}

public static T GetBestFit<T>(this IList<T> list, Func<T, T, bool> rule)
{
Comparison<T> c = new Comparison<T>((x, y) => (rule(x, y)) ? 1 : -1);
return list.GetBestFit(c);
}

Proxy Class for Making Any Object IComparable

I've been continuing my thinking on the topic of extension methods and selecting items out of an unsorted list. I made some changes to the selection extension methods in order to make them more manageable.

It led me to another topic which is pretty much unrelated. I was thinking about the proxy pattern and trying to find another way to use it. Right now, I only use it in my TextWriter proxy but haven't used it anywhere else. But, as I was working on all of these extension methods, I realized how easy it was to sort and compare objects that were IComparable and it kept my method signatures nice and clean.

The problem is, not everybody uses IComparable and it's not always better to subclass the object just to get it. Instead, I wrote a proxy class that takes your object and gives you an IComparable. I don't really have any uses for it yet and it's not "cooked" enough to be production ready, but it does do the trick and it is an example of the proxy pattern at work.
public class ProxyIComparable<T> : IComparable<T>
{
private T _object;

public IComparer<T> Comparer { get; private set; }
public Comparison<T> Comparison { get; private set; }

public ProxyIComparable(T obj, Comparison<T> comparison)
{
_object = obj;
Comparison = comparison;

Comparer = new ProxyComparer(Comparison);
}

public ProxyIComparable(T obj, IComparer<T> comparer)
{
_object = obj;
Comparer = comparer;

Comparison = new Comparison<T>((x, y) => Comparer.Compare(x, y));
}

public int CompareTo(T other)
{
return Comparison(_object, other);
}

private class ProxyComparer : IComparer<T>
{
private Comparison<T> _comparison;

public ProxyComparer(Comparison<T> comparison)
{
_comparison = comparison;
}

public int Compare(T x, T y)
{
return _comparison(x, y);
}
}
}

Friday, March 13, 2009

Implementing IComparer in C#

I was working on some extension methods today allowing me to pick an item out of an IList that best meets some criteria.

I started with just a delegate that takes two objects and returns a bool indicating that the first is a better fit than the second. I expanded the functionality to take an IComparer so that you can use the same comparison for the extension method that you use for sorting.

It was the first time I've written an IComparer so I thought I'd try a few techniques out. The first thing I wanted to do was to actually implement an IComparer (as opposed to just using the CompareTo method on the underlying comparison object). That is to say, I wanted to control returning -1, 0, or 1 myself. Here's what I came up with:
public class AgeComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
if (x.Age == y.Age) return 0;
return (x.Age > y.Age) ? 1 : -1;
}
}
It was pretty cool and it worked just fine. I needed another comparer that reversed directions so that I could sort in descending order. I tried 3 different ways (one way was to reverse the logic, but if the logic changed in one, it'd have to change in both and I didn't want that). One way to accomplish inverting the logic of an IComparer is to create an instance of the original comparer and reverse the parameters:
public class ReverseAgeComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
AgeComparer oc = new AgeComparer();
return oc.Compare(y, x);
}
}
The only downside to this method is that it sort of obfuscates what you're doing. I think negating the result of the original IComparer is a little clearer:
public class ReverseAgeComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
AgeComparer oc = new AgeComparer();
return oc.Compare(x, y) * -1;
}
}
With that in mind, I made the Compare method on the AgeComparer virtual and implemented my final attempt like this:
public class ReverseAgeComparer : AgeComparer
{
public override int Compare(Person x, Person y)
{
return base.Compare(x, y) * -1;
}
}

Extension Methods for Picking an Item out of an IList

So, I've been at it again with the extension methods. Earlier this week, I had a problem where I was getting back an array of items from a webservice. This webservice builds these objects from data in a database. The table that stores these data uses GUIDs as their primary key and there's a clustered index on the id column. As a result, if you pick 2 items from the list, there's about a 50-50 chance they're in the right order.

I really need them to be in the right order, so I tried to add an order by clause. Unfortunately, this particular webservice isn't really all that good and there's no way to order the objects returned from the database. In this case, the fact is that I really just needed the most recent record anyhow.

I know what you're thinkin' and I thought the same thing. I could just sort the array and pop the first one off the top. The problem is that (and in this case it was definitely not a problem) sorting takes O(n log n) time and it's pretty easy to get a max or a min in O(n) time. I wrote a quick, "get the most recent in linear time" loop to get the element I wanted, and it occurred to me that I found another good extension method.

The problem was, GetMostRecent isn't really all that useful because I could very wall want, GetOldest, GetFirstAlphabetically, GetHottest, etc. Instead, I implemented GetBestFit and I provided several overloads for passing comparison logic in.

The first implementation I had took a Func<T, T, bool> as the comparator; however, I later found the Comparison<T> class which became a pretty decent wrapper for the Func<T, T, bool> parameter. I thought about getting rid of it altogether, but I still like the syntax of the former. Here are those two extension methods:
public static T GetBestFit<T>(this IList<T> list, Func<T, T, bool> rule)
{
Comparison<T> c = new Comparison<T>((x, y) => (rule(x, y)) ? 1 : -1);
return list.GetBestFit(c);
}

public static T GetBestFit<T>(this IList<T> list, Comparison<T> comparison)
{
if (list == null || list.Count == 0)
throw new ArgumentException("You cannot get the best fit from an empty list!");

T currentFit = list[0];
for (int i = 1; i < list.Count; i++)
if (comparison(currentFit, list[i]) < 0)
currentFit = list[i];

return currentFit;
}
Then I realized that some objects already come with comparison information (id est, IComparable) and those objects deserve to have a GetBestFit that doesn't require you to write any comparison evaluators.
public static T GetBestFit<T>(this IList<T> list)
where T : IComparable<T>
{
if (list == null || list.Count == 0)
throw new ArgumentException("You cannot get the best fit from an empty list!");

T currentFit = list[0];
for (int i = 1; i < list.Count; i++)
if (currentFit.CompareTo(list[i]) < 0)
currentFit = list[i];

return currentFit;
}
Finally, I I thought that there are already classes responsible for comparing two objects for the sake of sorting and that getting the best fit is really just like sorting the list and taking the last item. I'm not really fixed on that one yet, but when you look at the way a comparer works and the way the sorting algorithm uses it, the "winner" always ends up at the end of the list. Anyhow, here's the IComparer implementation:
public static T GetBestFit<T>(this IList<T> list, IComparer<T> comparer)
{
if (list == null || list.Count == 0)
throw new ArgumentException("You cannot get the best fit from an empty list!");

T currentFit = list[0];
for (int i = 1; i < list.Count; i++)
if (comparer.Compare(currentFit, list[i]) < 0)
currentFit = list[i];

return currentFit;
}
I wrote a full set of test cases using NUnit, but I'll spare you having to read those. However, it seems like some implementation information might be handy, so here are a few examples. I also wrote several IComparers, but only listed one in the current post for the sake of example.

I wrote a very basic person class to use with various comparisons:
public class Person : IComparable<Person>
{
public Person(string name, DateTime birthdate)
{
Name = name;
Birthdate = birthdate;
}

public string Name { get; set; }
public DateTime Birthdate { get; set; }

public int Age
{
get
{
return DateTime.MinValue.Add(DateTime.Now.Subtract(Birthdate)).Year - 1;
}
}

public int CompareTo(Person other)
{
return this.Age.CompareTo(other.Age);
}

public class AgeComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
if (x.Age == y.Age) return 0;
return (x.Age > y.Age) ? 1 : -1;
}
}
}
I built a list of Persons and tested each extension with several different comparisons. Here are some syntax samples:
// uses IComparable.CompareTo
list.GetBestFit()

// the rest of the tests used these variables, you know
// just in case you want to run this code
Person oldest, first;

// uses an IComparer
oldest = list.GetBestFit(new Person.AgeComparer());
first = list.GetBestFit(new Person.ReverseAlphabeticalComparer());

// uses a Comparison
oldest = list.GetBestFit(new Comparison<Person>((x, y) => x.Age.CompareTo(y.Age)));
first = list.GetBestFit(new Comparison<Person>((x, y) => y.Name.CompareTo(x.Name)));

// uses a Func<T, T, bool> rule
oldest = list.GetBestFit((x, y) => x.Age > y.Age);
first = list.GetBestFit((x, y) => x.Name.CompareTo(y.Name) < 0);

Wednesday, March 11, 2009

Extension Method to Copy One Stream to Another

I don't think I could count the number of times I've written this code:
byte[] buffer = new byte[1024];
int bytesRead = 0;

do
{
bytesRead = source.Read(buffer, 0, buffer.Length);
target.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
With my recent cravings for a good reason to write an extension method and the frustration that there's no really good way to read from one stream and write it directly to another, I thought that it'd be really cool if I never had to write these lines of code again in my life!

I looked around and found that the MemoryStream class has a WriteTo(Stream) method. I thought, "I need one of those." At first, I called mine AppendTo(Stream) because I thought that it sounded more like what it was actually going to do. I also didn't know what would happen if I had an extension method with the same signature as an instance method.

I decided I should stop being lazy and look into it. I did some extension method research and found that "an extension method with the same name and signature as an interface or class method will never be called. At compile time, extension methods always have lower priority than instance methods defined in the type itself."

So, here's the extension method I ended up with:
public static void WriteTo(this Stream source, Stream target)
{
WriteTo(source, target, 1024);
}

public static void WriteTo(this Stream source, Stream target, int bufferLength)
{
byte[] buffer = new byte[bufferLength];
int bytesRead = 0;

do
{
bytesRead = source.Read(buffer, 0, buffer.Length);
target.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
}

IsEmpty and IsNull Extension Methods on the String Class

There have been a few times I've wanted a string.IsEmpty() method that would only return true if the string was actually empty. That's an extraordinarily uncommon situation, but more common than that would be a string.IsNull() that returns false if you pass it string.Empty.

The problem is, of course, if you're going to add extension methods for IsEmpty and IsNull, you really ought to go ahead and add one for IsNullOrEmpty so you can keep all of your method calls looking the same.

Here's a set of extension methods I wrote for helping out with dealing with null or empty strings:
public static bool IsEmpty(this string s)
{
return (s != null && s.Length == 0);
}

public static bool IsNull(this string s)
{
return (s == null);
}

public static bool IsNullOrEmpty(this string s)
{
return string.IsNullOrEmpty(s);
}

Extension Method to Get Custom Attributes with Reflection

I was working on my parameter validation with PostSharp proof of concept and I needed an easy way to get a list of custom attributes of a specific type from objects in the System.Reflection namespace like MethodInfo or ParameterInfo.

I noticed that objects which take custom attributes implement ICustomAttributeProvider. There is a GetCustomAttributes(Type, Boolean) overload which will get the custom attributes of a specific type, but I like the generic syntax better. I also prefer to return an IList rather than an array, but I don't really have any reasons for or against this preference.

I wrote a generic extension method for anything that is an ICustomAttributeProvider that will return a strongly typed list of attributes on the object:
public static List<T> GetAttributes<T>(this ICustomAttributeProvider pi) 
where T : Attribute
{
List<T> attrs = new List<T>();

foreach (object a in pi.GetCustomAttributes(typeof(T), false))
if (a is T) attrs.Add(a as T);

return attrs;
}
The usage is pretty cut and dry, but you can reference the afore mentioned article: Validate Parameters Using Attributes and PostSharp

Validate Parameters Using Attributes and PostSharp

I've been learning a lot about C# 4.0 lately and I have been very intrigued by the design by contract capabilities that will be added with the Microsoft Research Code Contracts project. One feature I'm particularly excited about is the static validation.

I've been working on a project which is little more than an abstract class and a bunch of test cases to verify that the outsourced implementers of this class make appropriate parameter validation on their overridden methods. I thought, "man, it sure would be nice if I could just put a code contract on my abstract class and then I wouldn't have to write all of these annoying unit tests."

Well, I just couldn't wait, so again I leveraged the pre-compiler flexibility of PostSharp and AoP concepts to simplify things a little (at least until code contracts are widely supported).

The first thing I did was define the contract for my parameter validation attributes:
[AttributeUsage(AttributeTargets.Parameter)]
public abstract class ParameterAttribute : Attribute
{
public abstract void CheckParameter(ParameterInfo parameter, object value);
}
Then, I wrote a method attribute with a method boundary aspect to process the parameter attributes:
[Serializable]
public class HasParameterAttributes : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
ParameterInfo[] pis = eventArgs.Method.GetParameters();
Object[] args = eventArgs.GetReadOnlyArgumentArray();

for (int i = 0; i < pis.Length; i++)
foreach (ParameterAttribute pa in pis[i].GetAttributes<ParameterAttribute>())
pa.CheckParameter(pis[i], args[i]);

base.OnEntry(eventArgs);
}
}
The version I wrote in honor of my friend Sir Nathan Rigsby is called CanHazParameterAttributes.

The HasParameterAttributes method attribute implementation uses an extension method I wrote to get a specific type of attributes from the PropertyInfo objects. You can find it in the article entitled: Extension Method to Get Custom Attributes with Reflection

I wrote two basic parameter validators to test the system:
public class NotNull : ParameterAttribute
{
public string Message { get; set; }
public override void CheckParameter(ParameterInfo parameter, object value)
{
if (value == null)
throw new ArgumentNullException(parameter.Name, Message);
}
}

public class NotEmpty : ParameterAttribute
{
public string Message { get; set; }

public override void CheckParameter(ParameterInfo parameter, object value)
{
if (value != null && value.ToString().Length == 0)
throw new ArgumentException(Message, parameter.Name);
}
}
The test I wrote does not execute like you would expect a unit test to execute. That is because I didn't have a lot of time to spend on this so I was too lazy to specify which test cases expect exceptions and which don't. If you run these test cases, you'll see that the ones which throw exceptions fail and the ones which don't throw exceptions pass. They perform as designed. Here's my NUnit test:
[TestFixture]
public class Tests
{
[Test, Combinatorial]
[HasParameterAttributes]
public void TestNotNull
([NotNull, Values(null, "", "Lulu")] string param1,
[NotEmpty, Values(null, "", "Lulu", 0)] object param2)
{ }
}

Extension Methods in C#

Extension methods have been around long enough now that most people probably already know what they are and what they're for, so I'll keep this part pretty short. Extension methods allow a developer to add methods to an already existing CLR type without decorating or sub-classing the type. This provides flexibility to strongly-typed languages like C#. For example, the fluent interface of LINQ heavily leverages extension methods.

I've been dying to come up with a good reason to write some extension methods, but until recently, I hadn't had much need for it. Now, I've written an extension method or two, have started using them in production code, and I'm addicted! Hence, the blog post you're reading now.

I also think I'm going to try a new format for posting "living documents." Previously, I've posted documents with the intent to change them periodically and post update notices. The problem is, the update notice is useless as a unit of blogging in and of itself. As a result, I think I'm going to post new extension methods separately and tag them "extension methods." That way, each additional post has value in and of itself and it'll be easy to keep track of them by browsing to extension methods search label.

Also, a convenient RSS feed is available.

Tuesday, March 3, 2009

A One Line Syntax Highlighter Script

Because programming is a repeated topic of this blog, I was pleased to find the syntax highlighter on Google Code. It's a set of javascripts that highlights code of several different languages and formats so that it is easy to read embedded in websites, but is still easy to copy to plain text.

The problem was, I wanted to be able to modify and configure the highlighter in one place and have it affect all of my blogs and my co-workers' blogs. I thought that you may want to use this technique yourself or you're more than welcome to just use the script I wrote.

To use my script, just add the following script tag to your page just above the closing body tag (i.e., </body>):
<script language='javascript' src='http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/SetupHighlighter.js'></script>
One caveat is that if I change something, it will affect your highlighed code; however, if you trust me not to do anything dumb, then it should be fine :).

If you'd like to implement the technique, here's what's in the SetupHighlighter.js file:
document.write("<link href='http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Styles/SyntaxHighlighter.css' rel='stylesheet' type='text/css'/>");

function include(script_filename) {
document.write('<scr' + 'ipt type="text/javascript" src="' + script_filename + '"></' + 'script' + '>');
}

include('http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/shCore.js');
include('http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/shBrushPython.js');
include('http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/shBrushCSharp.js');
include('http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/shBrushCss.js');
include('http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/shBrushJScript.js');
include('http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/shBrushPhp.js');
include('http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/shBrushRuby.js');
include('http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/shBrushSql.js');
include('http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/shBrushXml.js');
include('http://www.emeraldsoftwaregroup.com/content/SyntaxHighlighter/Uncompressed/ExecuteHighlighter.js');

All of the scripts that start with sh are the syntax highlighter brushes. I've included the ones I use here, but I'll obviously be adding the rest because other people using my hosted script may need them. The last script actually executes the highlighter, and here's what's in that file:
document.write('<scr' + 'ipt type="text/javascript">dp.SyntaxHighlighter.BloggerMode();dp.SyntaxHighlighter.HighlightAll("code");</script>')
I hope you enjoy it and let me know if you notice any problems or you have any requested changes.

Monday, March 2, 2009

Tabulate!!

How do you install Tabulate!! on your iphone?
  1. If you already clicked the link mentioned in step 2, you may now be feeling like you did something wrong. Well, you probably didn't. Just move on to step 3 and everything should be fine :).

  2. If you haven't already done so, click this link: The Tabulate Bookmarklet

  3. Bookmark this page

  4. Edit the newly created bookmark and remove everything before and including the first "?" leaving just the line that starts with "javascript."
It's just that easy!

The Tabulate Bookmarklet was created by Inventive Labs.

Opening a Link in a Window in Safari for the iPhone

I was looking around for a way to open a link in a new window in the iPhone Safari. I found out, much to my chagrin, that there isn't a native solution (I figured tapping with two fingers or something like that would do it, but no such luck). I did, however, find this cool little bookmarklet called Tabulate the web problem solvers over at Inventive Labs.

The tabulate bookmarklet replaces all of the links in a page with a small script. When you click on a link, it will open this prompt:Tabulate Prompt
You have the option of flagging the page to open later, opening the page in the current window, or my favorite &emdash; opening the page in a new window!

The only problem is that I hate syncing my iPhone so I have no way to install the thing. I posted a demo article about my Online Image Thumbnailer which included an iPhone installation method that I'm actually reusing for Tabulate as well.

So, here is the iPhone local installation procedure:
The Tabulate Bookmarklet.

Have fun!

Sunday, March 1, 2009

What Do You Do With HR-XML

I've been doing a lot of blogging lately, and I don't just mean posting a bunch of stories. I've been posting stories and digging and stumbling and all kinds of crazy things. Despite all of this, most of my hits are still on that one HR-XML article I wrote last year.

That brings up a few thoughts. First, if so many people are looking for information on HR-XML so consistently, they must be actively accepting it or rejecting it, and I'd like to know which and why. Second, I'd like to know who is doing what with HR-XML.

So, when you finish reading this post, I'd really appreciate your comments. What have you decided to do with HR-XML? What led you to this decision? What solutions have you already implemented with HR-XML to date?

My company has been evaluating HR-XML for several months, but we haven't yet implemented an HR-XML solution. We produce several components of an HR suite of software and we have integrated with a number of applications including background check vendors, HRMS, and ATS, but not one vendor has had an HR-XML integration solution (even one particular vendor which purports to be nearing an HR-XML integration solution).

We've been waiting for a partner to be HR-XML capable before we develop our own HR-XML integration. The problem is, I think everybody else is doing the same thing. Well, we're in a good position because the more customers we get and the more applications we have, the more we need our own internal applications.

So, we have decided to take the initiative to develop an HR-XML integration with all of our applications. This will give us a common and standard format with which to transfer data not only among our own applications, but with other applications and vendors as well. Future integrations will go through an "HR-XML layer," including custom integrations. By that, I mean rather than developing integrations to read from spreadsheets and CSV files and then to write directly to our databases, they will first be reformatted to HR-XML and will then be consumed by our HR-XML import engines.

Exports will be handled similarly. This gives our developers and our partners' developers a contract on which to map any imported or exported data without having to know anything about our internal data structures. We're hoping that as we integrate with more and more vendors, that they will also adopt HR-XML allowing all companies which provide human resources software and services to work harmoniously and interchangeably together throughout the entire employee life cycle.