Aslak,
yep - I remember the discussion.. I got to a pretty simple point, I've a
attached my code which does pretty well similar thing to yours by the
sounds of it. The next (big) step, is to read an entire database schema,
and create lots of entities with relationships and stuff. my code relies
on jenesis, with a couple of patches, which if you want I'll send you (not
sure of the size so wont post to list).
cheers
dim
On Fri, 7 Sep 2001 [EMAIL PROTECTED] wrote:
> Hi all.
>
> A couple of weeks ago I initiated a discussion about SQL generation. My
> desire was to have "something more generated" and do less coding. I have
> now changed my mind and made a tool (db2ejb) that does the oppsite. It
> reads DatabaseMetaData and generates source code with @tags for further
> prosessing by EJBGen/XDoclet. The idea is to start with a database, and
> have EJBs created with db2ejb + EJBGen/XDoclet, and do 0% coding except for
> the database modelling. I'm also working on automatic generation of tag
> libraries for easy manipulation of the EJBs.
>
> Dmitri mentioned he had something similar going on.
>
> Since I'm using WLS 6.1 and XDoclet doesn't support it yet, my
> implementation currently generates code for EJBGen only, but the generator
> part has a generic interface, so it's possible to write an implementation
> for XDoclet.
>
> If anybody is interested in this tool, I'll post my code.
>
> Aslak
>
>
> _______________________________________________
> Xdoclet-devel mailing list
> [EMAIL PROTECTED]
> https://lists.sourceforge.net/lists/listinfo/xdoclet-devel
>
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.DatabaseMetaData;
import java.sql.Types;
import java.sql.SQLException;
import org.inxar.jenesis.VirtualMachine;
import org.inxar.jenesis.CompilationUnit;
import org.inxar.jenesis.PackageClass;
import org.inxar.jenesis.Access;
import org.inxar.jenesis.Comment;
import org.inxar.jenesis.Type;
import org.inxar.jenesis.ClassMethod;
import org.inxar.jenesis.FormalParameter;
import org.inxar.jenesis.Method;
import org.inxar.jenesis.Invoke;
import org.inxar.jenesis.DocumentationComment;
import org.inxar.jenesis.Let;
public class ORMapper
{
/** Input parameters. */
private String
url, user, password, driver, catalog, schema, table;
/** Resources used in querying database. */
private Connection conn;
private DatabaseMetaData metaData;
private ResultSet columns;
private ResultSet pks;
/** params for generated source. */
private String dest;
private String pakkage = "ormapper";
private VirtualMachine vm;
private CompilationUnit unit;
private PackageClass cls;
private DocumentationComment classComment;
/** Looping vars */
private String property;
private Type type;
private short jdbcType;
/** map to store member -> type mapping */
private Map members = new HashMap();
/** maps to store member -> comment mappings */
private Map setterComments = new HashMap();
private Map getterComments = new HashMap();
/** Methods */
private ClassMethod ejbCreate;
private ClassMethod ejbPostCreate;
private ClassMethod loadData;
private FormalParameter dataRsParam;
private Let loadDataLet;
public void run()
{
try
{
openConnection();
loadDbMetaData();
queryTable();
constructBean();
queryPrimaryKeys();
constructCreateMethods();
unit.encode();
}
catch (SQLException sqle)
{
error("Database error: " + sqle.getMessage());
System.exit(-1);
}
catch (IOException ioe)
{
error("IO error: " + ioe.getMessage());
System.exit(-1);
}
catch (ClassNotFoundException cnfe)
{
error("Unable to find database driver: " + cnfe.getMessage());
}
finally
{
cleanup();
}
}
private void openConnection()
throws SQLException, ClassNotFoundException
{
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
}
private void loadDbMetaData()
throws SQLException
{
metaData = conn.getMetaData();
}
private void queryTable()
throws SQLException
{
columns = metaData.getColumns(catalog,
schema,
table,
null);
}
private void queryPrimaryKeys()
throws SQLException
{
pks = metaData.getPrimaryKeys(catalog,
schema,
table);
}
private void constructBean()
throws SQLException, IOException
{
vm = VirtualMachine.getVirtualMachine();
unit = vm.newCompilationUnit(dest);
constructStart();
while (columns.next())
{
constructProperty();
}
constructEnd();
}
private void constructStart()
throws SQLException
{
unit.setNamespace(pakkage);
cls = unit.newClass(getClassName());
cls.setAccess(Access.PUBLIC);
cls.isAbstract(true);
cls.addImplements("javax.ejb.EntityBean");
classComment = cls.javadoc("Generated " + getClassName() + " bean.");
classComment.addTag("ejb:entity", "persistent=\"CMP\" name=\"" +
getClassName() + "\" jndi-name=\"" + getClassName() +
"\"");
loadData = cls.newMethod(vm.newType(Type.VOID), "loadData");
loadData.setAccess(Access.PROTECTED);
dataRsParam = loadData.addParameter(vm.newType("java.sql.ResultSet"), "rs");
loadDataLet = loadData.newLet(vm.newType(getClassName() + "Data"));
loadDataLet.addAssign("data", vm.newClass(vm.newType(getClassName() +
"Data")));
}
private void constructProperty()
throws SQLException
{
setProperty();
setType();
saveType();
ClassMethod setter = cls.newMethod(vm.newType(Type.VOID), getSetterName());
setter.addParameter(type, property);
setter.setAccess(Access.PUBLIC);
setter.isAbstract(true);
DocumentationComment setterComment = setter.javadoc("setter for " + property);
setterComment.addTag("ejb:interface-method", "view-type=\"remote\"");
setterComments.put(property, setterComment);
ClassMethod getter = cls.newMethod(type, getGetterName());
getter.setAccess(Access.PUBLIC);
getter.isAbstract(true);
DocumentationComment getterComment = getter.javadoc("getter for " + property);
getterComment.addTag("ejb:persistent-field", "");
getterComment.addTag("ejb:interface-method", "view-type=\"remote\"");
getterComments.put(property, getterComment);
Invoke setDataProperty = vm.newInvoke("data", "set" + initCap(property));
setDataProperty.addArg(getGetXXXInvoke());
}
private void constructEnd()
throws SQLException
{
}
private void constructCreateMethods()
throws SQLException
{
ejbCreate = cls.newMethod(vm.newType(getClassName() + "PK"), "ejbCreate");
ejbCreate.setAccess(Access.PUBLIC);
ejbCreate.addThrows("javax.ejb.CreateException");
ejbPostCreate = cls.newMethod(vm.newType(Type.VOID), "ejbPostCreate");
ejbPostCreate.setAccess(Access.PUBLIC);
ejbPostCreate.addThrows("javax.ejb.CreateException");
while (pks.next())
{
property = pks.getString("COLUMN_NAME");
type = getType();
addEjbCreateParam();
addEjbPostCreateParam();
addPkComments();
}
}
private void addEjbCreateParam()
{
FormalParameter param = ejbCreate.addParameter(type, property);
Invoke setProp = vm.newInvoke(null, getSetterName());
setProp.addArg(vm.newVar(property));
ejbCreate.newStmt(setProp);
}
private void addEjbPostCreateParam()
{
ejbPostCreate.addParameter(type, property);
}
private void addPkComments()
{
getGetterComment().addTag("ejb:pk-field", "");
}
private void setProperty()
throws SQLException
{
property = columns.getString("COLUMN_NAME");
}
private Type getType()
{
return (Type) members.get(property);
}
private void setType()
throws SQLException
{
jdbcType = columns.getShort("DATA_TYPE");
switch (jdbcType)
{
case Types.INTEGER:
this.type = vm.newType(Type.INT);
return;
case Types.FLOAT:
this.type = vm.newType(Type.FLOAT);
return;
case Types.DOUBLE:
this.type = vm.newType(Type.DOUBLE);
return;
case Types.BIGINT:
this.type = vm.newType(Type.LONG);
return;
case Types.DATE:
this.type = vm.newType("java.sql.Date");
return;
case Types.VARCHAR:
this.type = vm.newType("java.lang.String");
return;
default:
warn("Unknown type for column " + property + ": " + type);
this.type = vm.newType("java.lang.Object");
return;
}
}
private void saveType()
{
members.put(property, type);
}
private String getSetterName()
{
return "set" + initCap(property);
}
private String getGetterName()
{
return "get" + initCap(property);
}
private DocumentationComment getGetterComment()
{
return (DocumentationComment) getterComments.get(property);
}
private DocumentationComment getSetterComment()
{
return (DocumentationComment) setterComments.get(property);
}
private Invoke getGetXXXInvoke()
{
String mthd = null;
switch (jdbcType)
{
case Types.
}
return vm.newInvoke("rs", mthd);
}
private String initCap(String str)
{
return str.substring(0, 1).toUpperCase()
+ str.substring(1);
}
private String getClassName()
{
// TODO: make this use columns.getString("TABLE_NAME") instead
return initCap(table);
}
private void cleanup()
{
if (columns != null)
{
try
{
columns.close();
}
catch (Exception e)
{
warn("Unable to close result set: " + e.getMessage());
}
}
if (conn != null)
{
try
{
conn.close();
}
catch (Exception e)
{
warn("Unable to close connection: " + e.getMessage());
}
}
}
public static void main(String[] arg)
{
ORMapper mapper = new ORMapper();
mapper.loadOptions(arg);
mapper.run();
}
ORMapper()
{
}
public ORMapper(String[] arg)
{
this();
loadOptions(arg);
}
public void loadOptions(String[] arg)
{
for (int i=0; i<arg.length; i++)
{
if (arg[i].equalsIgnoreCase("--url"))
{
url = arg[++i];
}
else if (arg[i].equalsIgnoreCase("--user"))
{
user = arg[++i];
}
else if (arg[i].equalsIgnoreCase("--password"))
{
password = arg[++i];
}
else if (arg[i].equalsIgnoreCase("--driver"))
{
driver = arg[++i];
}
else if (arg[i].equalsIgnoreCase("--catalog"))
{
catalog = arg[++i];
}
else if (arg[i].equalsIgnoreCase("--schema"))
{
schema = arg[++i];
}
else if (arg[i].equalsIgnoreCase("--table"))
{
table = arg[++i];
}
else if (arg[i].equalsIgnoreCase("--dest"))
{
dest = arg[++i];
}
else if (arg[i].equalsIgnoreCase("--package"))
{
pakkage = arg[++i];
}
else
{
warn("Argument " + arg[i] + ", not recognised. Ignoring.");
}
}
checkInputs();
}
private void checkInputs()
{
boolean error = false;
if (url == null)
{
error = true;
error("Required parameter URL missing.");
}
if (user == null)
{
error = true;
error("Required parameter user missing.");
}
if (driver == null)
{
error = true;
error("Required parameter driver missing.");
}
if (table == null)
{
error = true;
error("Required parameter table missing.");
}
if (error)
{
error("Unable to start due to missing parameters.");
showUsage();
System.exit(-1);
}
}
private void showUsage()
{
System.out.println("ORMapper usage:");
System.out.println(" java ORMapper args");
System.out.println("where args are one or more of:");
System.out.println(" --driver driver_class");
System.out.println(" --url database_url");
System.out.println(" --user database_user_name");
System.out.println(" --password database_password");
System.out.println(" --catalog catalog table is in");
System.out.println(" --schema schema table is in");
System.out.println(" --table table to generate bean from");
System.out.println(" --dest destination directory for output files.");
System.out.println(" --package package name for output class.");
System.out.println("You must provide at least URL, user, driver and table.");
}
private void info(String info)
{
System.out.println("[INFO] " + info);
}
private void warn(String warning)
{
System.err.println("[WARN] " + warning);
}
private void error(String error)
{
System.err.println("[ERROR] " + error);
}
}