node.invokeOnInit();
    public Node createNode(DbMapping dbm, ResultSet rs, DbColumn[] columns, int offset)                throws SQLException, IOException, ClassNotFoundException {        HashMap propBuffer = new HashMap();        String id = null;        String name = null;        String protoName = dbm.getTypeName();        DbMapping dbmap = dbm;        Node node = new Node();        for (int i = 0; i < columns.length; i++) {            // set prototype?            if (columns[i].isPrototypeField()) {                protoName = rs.getString(i+1+offset);                if (protoName != null) {                    dbmap = getDbMapping(protoName);                    if (dbmap == null) {                        // invalid prototype name!                        app.logError("Warning: Invalid prototype name: " + protoName +                                       " - using default");                        dbmap = dbm;                        protoName = dbmap.getTypeName();                    }                }            }            // set id?            if (columns[i].isIdField()) {                id = rs.getString(i+1+offset);                // if id == null, the object doesn't actually exist - return null                if (id == null) {                    return null;                }            }            // set name?            if (columns[i].isNameField()) {                name = rs.getString(i+1+offset);            }            Property newprop = new Property(node);            switch (columns[i].getType()) {                case Types.BIT:                    newprop.setBooleanValue(rs.getBoolean(i+1+offset));                    break;                case Types.TINYINT:                case Types.BIGINT:                case Types.SMALLINT:                case Types.INTEGER:                    newprop.setIntegerValue(rs.getLong(i+1+offset));                    break;                case Types.REAL:                case Types.FLOAT:                case Types.DOUBLE:                    newprop.setFloatValue(rs.getDouble(i+1+offset));                    break;                case Types.DECIMAL:                case Types.NUMERIC:                    BigDecimal num = rs.getBigDecimal(i+1+offset);                    if (num == null) {                        break;                    }                    if (num.scale() > 0) {                        newprop.setFloatValue(num.doubleValue());                    } else {                        newprop.setIntegerValue(num.longValue());                    }                    break;                case Types.VARBINARY:                case Types.BINARY:                    newprop.setStringValue(rs.getString(i+1+offset));                    break;                case Types.LONGVARBINARY:                case Types.LONGVARCHAR:                    try {                        newprop.setStringValue(rs.getString(i+1+offset));                    } catch (SQLException x) {                        Reader in = rs.getCharacterStream(i+1+offset);                        char[] buffer = new char[2048];                        int read = 0;                        int r;                        while ((r = in.read(buffer, read, buffer.length - read)) > -1) {                            read += r;                            if (read == buffer.length) {                                // grow input buffer                                char[] newBuffer = new char[buffer.length * 2];                                System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);                                buffer = newBuffer;                            }                        }                        newprop.setStringValue(new String(buffer, 0, read));                    }                    break;                case Types.CHAR:                case Types.VARCHAR:                case Types.OTHER:                    newprop.setStringValue(rs.getString(i+1+offset));                    break;                case Types.DATE:                case Types.TIME:                case Types.TIMESTAMP:                    newprop.setDateValue(rs.getTimestamp(i+1+offset));                    break;                case Types.NULL:                    newprop.setStringValue(null);                    break;                case Types.CLOB:                    Clob cl = rs.getClob(i+1+offset);                    if (cl==null) {                        newprop.setStringValue(null);                        break;                    }                    char[] c = new char[(int) cl.length()];                    Reader isr = cl.getCharacterStream();                    isr.read(c);                    newprop.setStringValue(String.copyValueOf(c));                    break;                default:                    newprop.setStringValue(rs.getString(i+1+offset));                    break;            }            if (rs.wasNull()) {                newprop.setStringValue(null);            }            propBuffer.put(columns[i].getName(), newprop);            // mark property as clean, since it's fresh from the db            newprop.dirty = false;        }        if (id == null) {            return null;        }        Hashtable propMap = new Hashtable();        DbColumn[] columns2 = dbmap.getColumns();        for (int i=0; i<columns2.length; i++) {            Relation rel = columns2[i].getRelation();            if (rel != null && (rel.reftype == Relation.PRIMITIVE ||                                rel.reftype == Relation.REFERENCE)) {                Property prop = (Property) propBuffer.get(columns2[i].getName());                if (prop == null) {                    continue;                }                prop.setName(rel.propName);                // if the property is a pointer to another node, change the property type to NODE                if ((rel.reftype == Relation.REFERENCE) && rel.usesPrimaryKey()) {                    // FIXME: References to anything other than the primary key are not supported                    prop.convertToNodeReference(rel.otherType);                }                propMap.put(rel.propName.toLowerCase(), prop);            }        }        node.init(dbmap, id, name, protoName, propMap, safe);        return node;    }