uncaught exceptions

Saturday, February 5, 2011

Office Remodel

You know how one house project turns into another? Anyway, long story short, I've been cleaning up old sci-fi books from my office and put a package of some really great ones to give to some friends. I hate letting these go, but I know they will be going to good homes. Hopefully, this will help me remember them because someday I'm going to make a list of my favorite sci-fi novels and these should be on there:

Richard Morgan, Broken Angels, Altered Carbon (I got to get his other one now, Woken Furies)

Alstair Reynolds, Diamond Dogs, Redemption Ark, Revelation Space (Need to get Chasm City)

Wednesday, January 19, 2011

Visual Studio 2010, Oracle 11g Client and XE 10g

Oracle's byzantine methods for configuration drive me up the wall. I struggled for 2.5 days trying to get their 11g development tools (ODT and ODP.NET) to work with Visual Studio 2010 and an already installed Oracle XE (10g).

The major issue was that the Universal Installer appeared to be loading the GAC with assemblies for version 2.112.2.0, but configured Visual Studio in the registry and machine.config files to use 4.112.2.0!

The final solution was to remove all Oracle assemblies from the GAC. After that, things started working, just needed to make sure ORACLE_HOME and PATH were configured appropriately, too. Hope that helps someone else!

Wednesday, October 22, 2008

UPDATED: Re-visiting MetaBuilder

I previously blogged about a new feature of MetaBuilder that I'm working on allows you to visit each object, as they are built, using a closure. I've updated the functionality so that the build visitor closure is given a CreateNodeEvent instance for each constructed node as follows:

public class CreateNodeEvent {
def name
def node
def parent
def isRoot // set to true, if the new node is a root node
}

If not a root node, the closure should return the node, or possibly a different node, when it is done.

Using a Build Visitor to Build a List of Root Nodes
An example closure that builds a list of all root nodes might be:

{ if(isRoot) { myList << it.node }; it.node }

In fact, I thought that usage might be so common that I included another set of buildList methods that returns a list of root nodes for you.

I'd also thought about exposing the ObjectGraphBuilder.postNodeCompletion() method, but it doesn't give you the node name, which is sometimes useful to have. It also doesn't tell you whether you're dealing with a root node (though you can probably derive that from the fact that parent == null for a root node.)

Using a Build Visitor to Build a Map of Root Nodes
Here's another build visitor example: say I have classes Order and OrderLine as follows and I want to use MetaBuilder to read Orders from a file into a map called orders, keyed on id:

class OrderLine {
def upc
def qty
def price
}

class Order {
def id
def lines = []
}

MetaBuilder mb = new MetaBuilder(getClass().getClassLoader())
mb.define {
order(factory: Order) {
properties {
id(req: true)
}
collections {
lines {
line (factory: OrderLine) {
properties {
upc(req: true)
qty(req: true)
price(req: true)
}
}
}
}
}
}

def orders = [:]
mb.build( { if(it.isRoot) { orders[it.node.id] = it.node }; it.node }, new File("orders.mb").toURL() )
A Hibernate Example
Andres Almiray's recent blog post on using ObjectGraphBuilder to create Grails fixtures inspired this next example, which extends the previous
example to insert each object into a database using Hibernate:

Session session = HibernateUtil.getSessionFactory().getCurrentSession();

session.beginTransaction()

mb.build( { if(it.isRoot) { session.save(it.node) }; it.node }, new File("orders.mb").toURL() )

session.getTransaction().commit()
Final Thoughts
One of the benefits of this feature is that it enables you to process large numbers of build objects without having to incur the overhead of building a list to contain them all.

Wednesday, October 15, 2008

Expanding barcode scans into EANs

*UPDATED*
I just discovered a bug in the check digit calculation, fixed below.  Essentially, the check digit is only subtracted from 10 if the sum_of_totals % 10 is greater than 0.  I'm sorry for any inconvenience!

I recently had a project where I had to use a barcode scanner to make scans of numbers that were possibly smaller than the 13 digit EAN standard. I had to then check these against the same number in a list, but the numbers in the list had been expanded to 13 digits using the algorithm below:

If the scanned number has 13 or more digits, return it.
If the scanned number has 12 digits, prepend a zero and return the result.

If the scanned number had 6 digits, treat it as a Zero Compressed UPC-E, expand it 11 digits using the following table and continue:

Last digit UPC-E equivalent is UPC-A equivalent is
0 XXNNN0 0XX000-00NNN + check
1 XXNNN1 0XX100-00NNN + check
2 XXNNN2 0XX200-00NNN + check
3 XXXNN3 0XXX00-000NN + check
4 XXXXN4 0XXXX0-0000N + check
5 XXXXX5 0XXXXX-00005 + check
6 XXXXX6 0XXXXX-00006 + check
7 XXXXX7 0XXXXX-00007 + check
8 XXXXX8 0XXXXX-00008 + check
9 XXXXX9 0XXXXX-00009 + check

If the number (as scanned or expanded) has less than 12 digits, left pad it to 12 digits using zeros, add a check digit, and return the result.

The check digit is computed as follows:
  1. Sum the digits in all odd positions, and multiply the result by 3.
  2. Sum the digits in all even positions.
  3. Sum the totals calculated in steps 2 and 3.
  4. *UPDATED* Check digit is sum_of_totals % 10 > 0 ? 10 - (sum_of_totals % 10) : 0
Here is my C# program that I used to work this out:
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1 {
    class Program {
        protected static int[][] upcPartialChecksumDigit = new int[][]{ 
            new int[] { 0 * 1, 1 * 1, 2 * 1, 3 * 1, 4 * 1, 5 * 1, 6 * 1, 7 * 1, 8 * 1, 9 * 1 }, // 0
            new int[] { 0 * 3, 1 * 3, 2 * 3, 3 * 3, 4 * 3, 5 * 3, 6 * 3, 7 * 3, 8 * 3, 9 * 3 }, // 1
            new int[] { 0 * 1, 1 * 1, 2 * 1, 3 * 1, 4 * 1, 5 * 1, 6 * 1, 7 * 1, 8 * 1, 9 * 1 }, // 2
            new int[] { 0 * 3, 1 * 3, 2 * 3, 3 * 3, 4 * 3, 5 * 3, 6 * 3, 7 * 3, 8 * 3, 9 * 3 }, // 3
            new int[] { 0 * 1, 1 * 1, 2 * 1, 3 * 1, 4 * 1, 5 * 1, 6 * 1, 7 * 1, 8 * 1, 9 * 1 }, // 4
            new int[] { 0 * 3, 1 * 3, 2 * 3, 3 * 3, 4 * 3, 5 * 3, 6 * 3, 7 * 3, 8 * 3, 9 * 3 }, // 5
            new int[] { 0 * 1, 1 * 1, 2 * 1, 3 * 1, 4 * 1, 5 * 1, 6 * 1, 7 * 1, 8 * 1, 9 * 1 }, // 6
            new int[] { 0 * 3, 1 * 3, 2 * 3, 3 * 3, 4 * 3, 5 * 3, 6 * 3, 7 * 3, 8 * 3, 9 * 3 }, // 7
            new int[] { 0 * 1, 1 * 1, 2 * 1, 3 * 1, 4 * 1, 5 * 1, 6 * 1, 7 * 1, 8 * 1, 9 * 1 }, // 8
            new int[] { 0 * 3, 1 * 3, 2 * 3, 3 * 3, 4 * 3, 5 * 3, 6 * 3, 7 * 3, 8 * 3, 9 * 3 }, // 9
            new int[] { 0 * 1, 1 * 1, 2 * 1, 3 * 1, 4 * 1, 5 * 1, 6 * 1, 7 * 1, 8 * 1, 9 * 1 }, // 10
            new int[] { 0 * 3, 1 * 3, 2 * 3, 3 * 3, 4 * 3, 5 * 3, 6 * 3, 7 * 3, 8 * 3, 9 * 3 }  // 11
        };

        /*
        Note 6 digit UPC-E codes are expanded to 12 digit UPC-A codesas follows:
        0  XXNNN0  00XX000-00NNN + check
        1  XXNNN1  00XX100-00NNN + check
        2  XXNNN2  00XX200-00NNN + check
        3  XXXNN3  00XXX00-000NN + check
        4  XXXXN4  00XXXX0-0000N + check
        5  XXXXX5  00XXXXX-00005 + check
        6  XXXXX6  00XXXXX-00006 + check
        7  XXXXX7  00XXXXX-00007 + check
        8  XXXXX8  00XXXXX-00008 + check
        9  XXXXX9  00XXXXX-00009 + check
        */
        public static string getUPC(string id) {
            if (id == null) return null;

            StringBuilder s = new StringBuilder("0", 11);
            if (id.Length == 6) {
                switch (id[5] - '0') {
                    case 0:
                        id = s.Append(id[0]).Append(id[1]).Append("00000").Append(id[2]).Append(id[3]).Append(id[4]).ToString();
                        break;
                    case 1:
                        id = s.Append(id[0]).Append(id[1]).Append("10000").Append(id[2]).Append(id[3]).Append(id[4]).ToString();
                        break;
                    case 2:
                        id = s.Append(id[0]).Append(id[1]).Append("20000").Append(id[2]).Append(id[3]).Append(id[4]).ToString();
                        break;
                    case 3:
                        id = s.Append(id[0]).Append(id[1]).Append(id[2]).Append("00000").Append(id[3]).Append(id[4]).ToString();
                        break;
                    case 4:
                        id = s.Append(id[0]).Append(id[1]).Append(id[2]).Append(id[3]).Append("00000").Append(id[4]).ToString();
                        break;
                    case 5:
                        id = s.Append(id[0]).Append(id[1]).Append(id[2]).Append(id[3]).Append(id[4]).Append("00005").ToString();
                        break;
                    case 6:
                        id = s.Append(id[0]).Append(id[1]).Append(id[2]).Append(id[3]).Append(id[4]).Append("00006").ToString();
                        break;
                    case 7:
                        id = s.Append(id[0]).Append(id[1]).Append(id[2]).Append(id[3]).Append(id[4]).Append("00007").ToString();
                        break;
                    case 8:
                        id = s.Append(id[0]).Append(id[1]).Append(id[2]).Append(id[3]).Append(id[4]).Append("00008").ToString();
                        break;
                    case 9:
                        id = s.Append(id[0]).Append(id[1]).Append(id[2]).Append(id[3]).Append(id[4]).Append("00009").ToString();
                        break;
                    default:
                        return null;
                }
            }
            if (id.Length < 12) {
                id = id.PadLeft(12, '0');
                int checksum = 0;
                for (int i = 0; i < 12; i++) { //should get unrolled by compiler hopefully
                    int c = id[i] - '0';
                    if (c < 0 || c > 9) return null;
                    int partial = upcPartialChecksumDigit[i][c];
                    checksum += partial;
                }
                // *UPDATED*
                char checksumDigit = '0';
                checksum %= 10;
                if(checksum > 0) checksumDigit += (char)(10 - checksum);
                id += checksumDigit;
            }
            else if (id.Length == 12) {
                id = '0' + id;
            }
            return id;
        }
        


        static void Main(string[] args) {
            string s = ConvertUPC("654321");
            Console.WriteLine();
        }

        public static String ConvertUPC(string arg) {
            return arg + " -> " + getUPC(arg);
        }
    }
}

Friday, September 5, 2008

Catching up!

A lot has happened since my last post: a vacation in France, the start of a new school year for the kids and the first release of a new Groovy utility that I've been working on, MetaBuilder.

MetaBuilder offers a number of features that make creating and using new builders safer and easier. First and foremost, it lets you specify your builder using a simple build language with lots of functionality to validate and control how objects are built.

Here's a Groovy script example to give you the flavor of it:

import groovytools.builder.*

MetaBuilder mb = new MetaBuilder()

mb.define {
customer {
properties {
name(req: true)
age(check: 1..120)
sex(check: ~/M|F/)
}
}
}

def aCustomer = mb.build {
customer(name: 'J. Doe', age: 25, sex: 'M')
}

If you manage to mistype a property name or violate a check constraint, MetaBuilder will throw an exception.

Wednesday, July 9, 2008

Introducing: 'uncaught exceptions'

Welcome to uncaught exceptions wherein I'll be sharing all sorts of things I come across while developing software and some other things, too.

I'm primarily a Java software developer, but I do a lot with Oracle and most recently, Groovy. (If you're a serious Java developer and you haven't seen Groovy yet, head on over there and check it out.)

One of the things that I've been working on for fun is groovytools, a collection of Groovy tools and experiments. The first of which is GPP, a Groovy port of VPP, which is an Ant and Velocity-based preprocessor. Either GPP or VPP can be a useful for code generation, mail-merge and numerous other template-based tasks. In general, I find Groovy much more convenient and less quirky to use than the venerable Velocity. In fact, the port to Groovy was extremely smooth and since then I haven't used Velocity again.

My advice to all programmers just getting started:
while(true) {
try { ... }
catch (Exception e) { ... }
}

For everyone else, never give up, just keep trying!
Content © didge

About Me

didge is my professional nickname, it's short for digital dave
Powered By Blogger