You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2006/07/21 09:55:22 UTC

svn commit: r424221 - /db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/

Author: arminw
Date: Fri Jul 21 00:55:21 2006
New Revision: 424221

URL: http://svn.apache.org/viewvc?rev=424221&view=rev
Log:
Initial check in of forward engineering tool by Tom Antony, see OJB-112
port (support for JDK1.3 needed) source to OJB 1.0.x.
There are issues when generating JavaBeans and torque-xml file:
- Bean Generation: No support for package structure
- Bean Generation: No support for inner classes
- SQL Gneration: Duplicated FK definitions. Seems caused by "extent-class" settings (defined sub-classes))
- SQL Gneration: Duplicated columns and missing columns in m:n indirection tables

Added:
    db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/
    db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/BeanDescriptor.java
    db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/BeanGenerator.java
    db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/ForwardRepositoryTask.java
    db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/RepositoryXmlProcessor.java
    db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/SQLStructures.java
    db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/TorqueSchemaGenerator.java
    db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/Utils.java

Added: db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/BeanDescriptor.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/BeanDescriptor.java?rev=424221&view=auto
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/BeanDescriptor.java (added)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/BeanDescriptor.java Fri Jul 21 00:55:21 2006
@@ -0,0 +1,85 @@
+package org.apache.ojb.tools.mapping.forward;
+
+/* Copyright 2002-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+
+/**
+ * Descriptor for a Java bean.
+ *
+ * @author Tom Antony
+ * @version 1.0, 03-MAY-2006.
+ */
+public class BeanDescriptor
+{
+    private String packageName;
+    private String className;
+    private String baseClass;
+    private String [] interfaces;
+    private ArrayList attributes;
+    private ArrayList types;
+
+    /**
+     * Create a new BeanDescriptor object.
+     *
+     * @param    packageName the package name of the bean
+     * @param    className the class name of the bean
+     * @param    baseClass the parent class of the bean
+     * @param    interfaces array of interface names implemented by the bean
+     * @param    attributes the bean attributes
+     * @param    types        types for bean attributes, should match attributes in order
+     */
+    public BeanDescriptor(String packageName, String className, String baseClass,
+                          String [] interfaces, ArrayList attributes, ArrayList types)
+    {
+        this.packageName = packageName;
+        this.className = className;
+        this.baseClass = baseClass;
+        this.interfaces = interfaces;
+        this.attributes = attributes;
+        this.types = types;
+    }
+
+    public String packageName()
+    {
+        return packageName;
+    }
+
+    public String className()
+    {
+        return className;
+    }
+
+    public String baseClass()
+    {
+        return baseClass;
+    }
+
+    public String[] interfaces()
+    {
+        return interfaces;
+    }
+
+    public ArrayList attributes()
+    {
+        return attributes;
+    }
+
+    public ArrayList types()
+    {
+        return types;
+    }
+}
\ No newline at end of file

Added: db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/BeanGenerator.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/BeanGenerator.java?rev=424221&view=auto
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/BeanGenerator.java (added)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/BeanGenerator.java Fri Jul 21 00:55:21 2006
@@ -0,0 +1,187 @@
+package org.apache.ojb.tools.mapping.forward;
+
+/* Copyright 2002-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.util.ArrayList;
+
+/**
+ * Generator for Java bean source.
+ *
+ * @author Tom Antony
+ * @version 1.0, 03-MAY-2006.
+ */
+public class BeanGenerator
+{
+    // output directory into which bean source code is generated.
+    private String outputDirectory;
+
+    /**
+     * Creates a new instance of the bean generator for the specified output directory.
+     *
+     * @param outputDirectory the output directory into which bean source code is generated.
+     */
+    public BeanGenerator(String outputDirectory)
+    {
+        this.outputDirectory = outputDirectory;
+    }
+
+    private static String capitalizeMemberField(String str)
+    {
+        String s = str.substring(0, 1);
+        s = s.toUpperCase();
+        s += str.substring(1);
+        return s;
+    }
+
+    private static String generateTypeDeclaration(String attribute, String type)
+    {
+        StringBuffer buf = new StringBuffer(100);
+
+        buf.append("\n\tprivate ");
+        buf.append(type);
+        buf.append(" ");
+        buf.append(attribute);
+        buf.append(";");
+
+        return buf.toString();
+    }
+
+    private static String generateGetMethod(String attribute, String type)
+    {
+        StringBuffer buf = new StringBuffer(100);
+
+        buf.append("\n\tpublic ");
+        buf.append(type);
+        buf.append(" get");
+        buf.append(capitalizeMemberField(attribute));
+        buf.append("()");
+        buf.append(" { return ");
+        buf.append(attribute);
+        buf.append("; }");
+
+        return buf.toString();
+    }
+
+    private static String generateSetMethod(String attribute, String type)
+    {
+        StringBuffer buf = new StringBuffer(100);
+
+        buf.append("\n\tpublic ");
+        buf.append("void ");
+        buf.append(" set");
+        buf.append(capitalizeMemberField(attribute));
+        buf.append("(");
+        buf.append(type);
+        buf.append(" ");
+        buf.append(attribute);
+        buf.append(")");
+        buf.append(" { this.");
+        buf.append(attribute);
+        buf.append(" = ");
+        buf.append(attribute);
+        buf.append("; }");
+
+        return buf.toString();
+    }
+
+    /**
+     * Generate the source for the Java bean.
+     *
+     * @param beanDescription the bean descriptor.
+     */
+    public void generate(BeanDescriptor beanDescription) throws Exception
+    {
+        StringBuffer buf = new StringBuffer(100);
+
+        if(beanDescription.packageName() != null && beanDescription.packageName().trim().length() > 0)
+        {
+            buf.append("package ");
+            buf.append(beanDescription.packageName());
+            buf.append(";\n");
+        }
+
+        buf.append("\n");
+        buf.append("public class ");
+        buf.append(beanDescription.className());
+
+        if(beanDescription.baseClass() != null)
+            buf.append(" extends ").append(beanDescription.baseClass());
+
+        if(beanDescription.interfaces() != null)
+        {
+            buf.append(" implements ");
+            for(int i = 0; i < beanDescription.interfaces().length; i++)
+            {
+                buf.append(beanDescription.interfaces()[i]);
+                if(i < beanDescription.interfaces().length - 1) buf.append(" , ");
+            }
+        }
+
+        buf.append("\n");
+
+        buf.append("{");
+
+        for(int i = 0; i < beanDescription.attributes().size(); i++)
+        {
+            String attribute = (String) beanDescription.attributes().get(i);
+            String type = (String) beanDescription.types().get(i);
+            buf.append(generateTypeDeclaration(attribute, type));
+        }
+
+        buf.append("\n");
+
+        for(int i = 0; i < beanDescription.attributes().size(); i++)
+        {
+            String attribute = (String) beanDescription.attributes().get(i);
+            String type = (String) beanDescription.types().get(i);
+
+            buf.append(generateSetMethod(attribute, type));
+            buf.append(generateGetMethod(attribute, type));
+
+            buf.append("\n");
+        }
+
+        buf.append("\n");
+
+        buf.append("}");
+
+        FileWriter fwr = new FileWriter(new File(outputDirectory, beanDescription.className() + ".java"));
+        fwr.write(buf.toString());
+        fwr.close();
+    }
+
+    public static void main(String args[]) throws Exception
+    {
+        BeanGenerator gen = new BeanGenerator(null);
+
+        ArrayList attributes = new ArrayList();
+        ArrayList types = new ArrayList();
+
+        attributes.add("name");
+        types.add("String");
+
+        attributes.add("age");
+        types.add("int");
+
+        BeanDescriptor description = new BeanDescriptor(null, "Customer", "Person",
+                new String []{"XYZ", "ABC"},
+                attributes, types
+        );
+        gen.generate(description);
+	}
+}
\ No newline at end of file

Added: db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/ForwardRepositoryTask.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/ForwardRepositoryTask.java?rev=424221&view=auto
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/ForwardRepositoryTask.java (added)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/ForwardRepositoryTask.java Fri Jul 21 00:55:21 2006
@@ -0,0 +1,87 @@
+package org.apache.ojb.tools.mapping.forward;
+
+/* Copyright 2002-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.BuildException;
+import org.apache.commons.lang.exception.ExceptionUtils;
+
+/**
+ * Ant task for {@link RepositoryXmlProcessor}.
+ *
+ * @version $Id: $
+ */
+public class ForwardRepositoryTask extends Task
+{
+    private String input;
+    private String beanOutput;
+    private String torqueOutput;
+
+    public ForwardRepositoryTask()
+    {
+    }
+
+    public void execute() throws BuildException
+    {
+        super.execute();
+        getProject().log("Start OJB Forward Engineering");
+        getProject().log("Input: " + getInput());
+        getProject().log("Bean output: " + getBeanOutput());
+        getProject().log("Torque output: " + getTorqueOutput());
+
+        try
+        {
+            RepositoryXmlProcessor processor = new RepositoryXmlProcessor(getInput(), getBeanOutput(), getTorqueOutput());
+            processor.generateSQL();
+            processor.generateJavaCode();
+        }
+        catch(Exception e)
+        {
+            getProject().log("Forward Engineering failed: " + ExceptionUtils.getFullStackTrace(e));
+            throw new BuildException("Can't finish forward engineering", e);
+        }
+    }
+
+    public String getInput()
+    {
+        return input;
+    }
+
+    public void setInput(String input)
+    {
+        this.input = input;
+    }
+
+    public String getBeanOutput()
+    {
+        return beanOutput;
+    }
+
+    public void setBeanOutput(String beanOutput)
+    {
+        this.beanOutput = beanOutput;
+    }
+
+    public String getTorqueOutput()
+    {
+        return torqueOutput;
+    }
+
+    public void setTorqueOutput(String torqueOutput)
+    {
+        this.torqueOutput = torqueOutput;
+    }
+}

Added: db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/RepositoryXmlProcessor.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/RepositoryXmlProcessor.java?rev=424221&view=auto
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/RepositoryXmlProcessor.java (added)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/RepositoryXmlProcessor.java Fri Jul 21 00:55:21 2006
@@ -0,0 +1,651 @@
+package org.apache.ojb.tools.mapping.forward;
+
+/* Copyright 2002-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+
+import java.util.Set;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.List;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.apache.commons.lang.StringUtils;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+/**
+ * Utility to process OJB's repository.xml file and generate Java bean source code and
+ * SQL schema in Torque XML format.
+ *
+ * Auto generated indirection tables
+ * ---------------------------------
+ *
+ * If there are no explicit mappings for an indirection table, the utility generates the SQL
+ * schema for it including referential constraints.
+ *
+ * An indirection table associates two tables. So it will contain two referential constraints,
+ * one for each of the associated table. The primary key will be a combination of the foreign
+ * keys for both of the associated tables.
+ *
+ * @author Tom Antony
+ * @version 1.0, 03-MAY-2006.
+ */
+public class RepositoryXmlProcessor
+{
+    // the output Torque xml file name.
+    private String torqueXmlFile = "ojb-torque.xml";
+
+    // the output directory for generated torque xml.
+    private String torqueOutputDirectory;
+
+    // the output directory for generated java beans.
+    private String beanOutputDirectory;
+
+    // the DOM document holding OJB mappings.
+    private Document doc;
+
+    // auto generated indirection tables.
+    private Map indirectionTables = new HashMap();
+
+    // tables which need merging of multiple mapping definitions.
+    private Map deferredTables = new HashMap();
+
+    // mapping between JDBC/SQL and Java types.
+    private static HashMap typeMap = new HashMap();
+
+    // http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/mapping.html
+    static
+    {
+        typeMap.put("BIT", "boolean");
+
+        typeMap.put("SMALLINT", "short");
+        typeMap.put("INTEGER", "int");
+        typeMap.put("BIGINT", "long");
+
+        typeMap.put("FLOAT", "float");
+        typeMap.put("DOUBLE", "double");
+        typeMap.put("REAL", "float");
+        typeMap.put("NUMERIC", "java.math.BigDecimal");
+        typeMap.put("DECIMAL", "java.math.BigDecimal");
+
+        typeMap.put("CHAR", "String");
+        typeMap.put("VARCHAR", "String");
+        typeMap.put("LONGVARCHAR", "String");
+
+        typeMap.put("CLOB", "java.sql.Clob");
+        typeMap.put("BLOB", "java.sql.Blob");
+        typeMap.put("ARRAY", "java.sql.Array");
+        typeMap.put("STRUCT", "java.sql.Struct");
+        typeMap.put("REF", "java.sql.Ref");
+
+        typeMap.put("BINARY", "byte []");
+        typeMap.put("VARBINARY", "byte []");
+        typeMap.put("LONGVARBINARY", "byte []");
+
+        typeMap.put("DATE", "java.sql.Date");
+        typeMap.put("TIME", "java.sql.Time");
+        typeMap.put("TIMESTAMP", "java.sql.Timestamp");
+    }
+
+    /**
+     * Creates a new instance of the repository xml processor.
+     *
+     * @param    repositoryXml the path of the repository.xml to be processed.
+     * @param    torqueOutputDirectory the output directory into which java beans and Torque xml are
+     * generated, specify null for current directory.
+     * @param    beanOutputDirectory the name of the Torque xml file, specify null for the default
+     * which is is 'ojb-torque.xml'.
+     */
+    public RepositoryXmlProcessor(String repositoryXml, String torqueOutputDirectory, String beanOutputDirectory) throws Exception
+    {
+        if(torqueOutputDirectory != null)
+            this.torqueOutputDirectory = torqueOutputDirectory;
+        if(beanOutputDirectory != null)
+            this.beanOutputDirectory = beanOutputDirectory;
+
+        // create output directory if it does not exist.
+        if(!new File(torqueOutputDirectory).exists())
+            new File(torqueOutputDirectory).mkdir();
+
+        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        doc = builder.parse(new File(repositoryXml));
+    }
+
+    /*
+      *	Convinience method.
+      */
+    private Table getTableInfo(Element clsDescElem)
+    {
+        return getTableInfo(clsDescElem, true);
+    }
+
+    /*
+      *	Get the table description associated with a <class-descriptor> element.
+      *  If recurse is true, explore <reference-descriptor> elements, else return after
+      *	filling in the columns.
+      */
+    private Table getTableInfo(Element clsDescElem, boolean recurse)
+    {
+        Table table = new Table();
+
+        table.name = clsDescElem.getAttribute("table");
+
+        Map fieldColumnMap = new HashMap();
+
+        NodeList fldDescList = clsDescElem.getElementsByTagName("field-descriptor");
+        for(int i = 0; i < fldDescList.getLength(); i++)
+        {
+            Element fldDescElem = (Element) fldDescList.item(i);
+
+            String fieldName = fldDescElem.getAttribute("name");
+            String columnName = fldDescElem.getAttribute("column");
+            String jdbcType = fldDescElem.getAttribute("jdbc-type");
+            String primaryKey = fldDescElem.getAttribute("primarykey");
+            String nullable = fldDescElem.getAttribute("nullable");
+            String autoincriment = fldDescElem.getAttribute("autoincrement");
+            String length = fldDescElem.getAttribute("length");
+
+            Column column = new Column();
+            table.columns.add(column);
+
+            column.name = columnName;
+            column.jdbcType = jdbcType;
+            column.length = length;
+
+            if(primaryKey != null && primaryKey.equals("true"))
+                column.isPrimaryKey = true;
+            if(nullable != null && nullable.equals("false"))
+                column.isNullable = false;
+            if(autoincriment != null && autoincriment.equals("true"))
+                column.isAutoIncriment = true;
+
+            fieldColumnMap.put(fieldName, columnName);
+        }
+
+        // If recurse is false, we are calling just to get parent table's primary keys, so return.
+        if(!recurse)
+            return table;
+
+        // Generate foreignkey definitions.
+        NodeList refDescList = clsDescElem.getElementsByTagName("reference-descriptor");
+        for(int i = 0; i < refDescList.getLength(); i++)
+        {
+            Element refDescElem = (Element) refDescList.item(i);
+            String refClassName = refDescElem.getAttribute("class-ref");
+
+            // First, figure out the foreign table.
+            Element clsDescElemForeignTable = findFirstMappedClass(doc, refClassName);
+            Table foreignTable = getTableInfo(clsDescElemForeignTable, false);
+            ForeignKey foreignKey = new ForeignKey();
+            table.foreignKeys.add(foreignKey);
+            foreignKey.foreignTable = foreignTable.name;
+
+            // Iterate through foreignkeys defined in the current reference description
+            NodeList fkList = refDescElem.getElementsByTagName("foreignkey");
+            for(int j = 0; j < fkList.getLength(); j++)
+            {
+                Element fkElem = (Element) fkList.item(j);
+                String fkFieldName = fkElem.getAttribute("field-ref");
+                String fkColumn = (String) fieldColumnMap.get(fkFieldName);
+
+                foreignKey.localColumns.add(fkColumn);
+            }
+
+            // Add primary keys of the foreign table, in order.
+            for(int j = 0; j < foreignTable.columns.size(); j++)
+            {
+                Column foreignColumn = (Column) foreignTable.columns.get(j);
+                if(foreignColumn.isPrimaryKey)
+                    foreignKey.foreignColumns.add(foreignColumn.name);
+            }
+        }
+
+        // read-in index definitions
+        NodeList indexDescList = clsDescElem.getElementsByTagName("index-descriptor");
+        for(int i = 0; i < indexDescList.getLength(); i++)
+        {
+            Element indexDescElem = (Element) indexDescList.item(i);
+            String name = indexDescElem.getAttribute("name");
+            String unique = indexDescElem.getAttribute("unique");
+            Index index = new Index();
+            table.indexes.add(index);
+            index.name = name;
+            if(unique != null && unique.equals("true"))
+                index.isUnique = true;
+
+            NodeList indexColumnList = indexDescElem.getElementsByTagName("index-column");
+            for(int j = 0; j < indexColumnList.getLength(); j++)
+            {
+                Element indexColumnElem = (Element) indexColumnList.item(j);
+                String indexColumnName = indexColumnElem.getAttribute("name");
+                index.columns.add(indexColumnName);
+            }
+        }
+
+        return table;
+    }
+
+    /*
+      *	Returns set of all table names.
+      */
+    private Set allTables(Document doc)
+    {
+        Set tableNames = new HashSet();
+        NodeList clsDescList = doc.getElementsByTagName("class-descriptor");
+        for(int i = 0; i < clsDescList.getLength(); i++)
+        {
+            Element clsDescElem = (Element) clsDescList.item(i);
+            String tableName = clsDescElem.getAttribute("table");
+            tableNames.add(tableName);
+        }
+        return tableNames;
+    }
+
+    /*
+      *	Returns set of names of tables mapped to multiple classes.
+      */
+    private Set duplicateTables(Document doc)
+    {
+        Set workingSet = new HashSet();
+        Set duplicateSet = new HashSet();
+
+        NodeList clsDescList = doc.getElementsByTagName("class-descriptor");
+        for(int i = 0; i < clsDescList.getLength(); i++)
+        {
+            Element clsDescElem = (Element) clsDescList.item(i);
+            String tableName = clsDescElem.getAttribute("table");
+            if(workingSet.contains(tableName))
+                duplicateSet.add(tableName);
+            else
+                workingSet.add(tableName);
+        }
+        return duplicateSet;
+    }
+
+    /*
+      *	Merge the src table into the target.
+      */
+    private void mergeTables(Table target, Table src)
+    {
+        // merge columns
+        for(int i = 0; i < src.columns.size(); i++)
+        {
+            Column srcColumn = (Column) src.columns.get(i);
+            if(!target.columns.contains(srcColumn))
+            {
+                target.columns.add(srcColumn);
+            }
+        }
+
+        // merge foreign keys
+        for(int i = 0; i < src.foreignKeys.size(); i++)
+        {
+            ForeignKey srcForeignKey = (ForeignKey) src.foreignKeys.get(i);
+            if(!target.foreignKeys.contains(srcForeignKey))
+            {
+                target.foreignKeys.add(srcForeignKey);
+            }
+        }
+
+        // merge indexes.
+        for(int i = 0; i < src.indexes.size(); i++)
+        {
+            Index srcIndex = (Index) src.indexes.get(i);
+            if(!target.indexes.contains(srcIndex))
+            {
+                target.indexes.add(srcIndex);
+            }
+        }
+    }
+
+    /** Generate the Torque format SQL schema definitions. */
+    public void generateSQL() throws Exception
+    {
+        Set allTables = allTables(doc);
+        Set duplicateTables = duplicateTables(doc);
+
+        NodeList clsDescList = doc.getElementsByTagName("class-descriptor");
+
+        File out = new File(torqueOutputDirectory);
+        out.mkdirs();
+        FileWriter fwr = new FileWriter(new File(torqueOutputDirectory, torqueXmlFile));
+        fwr.write(TorqueSchemaGenerator.torquePrefix());
+
+        for(int i = 0; i < clsDescList.getLength(); i++)
+        {
+            Element clsDescElem = (Element) clsDescList.item(i);
+            Table currentTable = getTableInfo(clsDescElem);
+            String tableName = currentTable.name;
+            if(StringUtils.isNotBlank(tableName))
+            {
+                try
+                {
+                    /*
+                    *	If table has multiple class mappings, keep the table structure in the deferred
+                    *	list and keep merging later definitions we encounter.
+                    */
+                    if(duplicateTables.contains(tableName))
+                    {
+                        Table existingTable = (Table) deferredTables.get(tableName);
+                        if(existingTable == null)
+                            deferredTables.put(tableName, currentTable);
+                        else
+                            mergeTables(existingTable, currentTable);
+                    }
+                    else
+                    {
+                        String tableStr = TorqueSchemaGenerator.generateTorqueSchema(currentTable);
+                        fwr.write(tableStr);
+                    }
+
+                    // Auto generate table definition for indirection tables if any.
+                    NodeList colDescList = clsDescElem.getElementsByTagName("collection-descriptor");
+
+                    for(int j = 0; j < colDescList.getLength(); j++)
+                    {
+                        Element colDescElem = (Element) colDescList.item(j);
+                        String indirectionTableName = colDescElem.getAttribute("indirection-table");
+
+                        if(indirectionTableName != null && indirectionTableName.trim().length() > 0)
+                        {
+                            Table indirectionTable = (Table) indirectionTables.get(indirectionTableName);
+
+                            if(indirectionTable == null)
+                            {
+                                indirectionTable = new Table();
+                                indirectionTable.name = indirectionTableName;
+
+                                indirectionTables.put(indirectionTableName, indirectionTable);
+                            }
+
+                            // Generate one foreign key constraint for the current table.
+                            ForeignKey foreignKey = new ForeignKey();
+
+                            indirectionTable.foreignKeys.add(foreignKey);
+
+                            foreignKey.foreignTable = currentTable.name;
+
+                            NodeList fkSelfList = colDescElem.getElementsByTagName("fk-pointing-to-this-class");
+                            for(int k = 0; k < fkSelfList.getLength(); k++)
+                            {
+                                Element fkSelfElem = (Element) fkSelfList.item(k);
+                                String columnName = fkSelfElem.getAttribute("column");
+
+                                Column column = new Column();
+                                indirectionTable.columns.add(column);
+
+                                column.name = columnName;
+                                foreignKey.localColumns.add(columnName);
+
+                                /*
+                                *	Foreign keys pointing to current table in the <collection-descriptor>
+                                *	element should match primary keys of current table in the same sequence.
+                                *	Match attributes for indirection columns with corresponding primary key columns.
+                                */
+                                String foreignColumnName = null;
+                                String foreignColumnType = null;
+                                String foreignColumnLength = null;
+
+                                int primaryKeyCounter = 0;
+                                for(int q = 0; q < currentTable.columns.size(); q++)
+                                {
+                                    Column currentTableColumn = (Column) currentTable.columns.get(q);
+                                    if(currentTableColumn.isPrimaryKey)
+                                    {
+                                        if(primaryKeyCounter == k)
+                                        {
+                                            foreignColumnName = currentTableColumn.name;
+                                            foreignColumnType = currentTableColumn.jdbcType;
+                                            foreignColumnLength = currentTableColumn.length;
+                                            break;
+                                        }
+                                        else
+                                            primaryKeyCounter++;
+                                    }
+                                }
+
+                                column.jdbcType = foreignColumnType;
+                                column.length = foreignColumnLength;
+                                foreignKey.foreignColumns.add(foreignColumnName);
+
+                                // All indirection columns become part of primary key for indirection table.
+                                column.isPrimaryKey = true;
+                                column.isNullable = false;
+                            }
+                        }
+                    }
+                }
+                catch(Exception e)
+                {
+                    throw new ForwardException("Error while performing table: " + currentTable, e);
+                }
+            }
+        }
+
+        // Generate deferred tables at the end.
+
+        Set defKeySet = deferredTables.keySet();
+        Iterator defKeysItr = defKeySet.iterator();
+        while(defKeysItr.hasNext())
+        {
+            String tableName = (String) defKeysItr.next();
+            Table defferedTable = (Table) deferredTables.get(tableName);
+
+            String tableStr = TorqueSchemaGenerator.generateTorqueSchema(defferedTable);
+            fwr.write(tableStr);
+        }
+
+        /*
+           *	Generate tables for indirection tables at the end. Table structure for an
+           *	indirection table gets filled up after processing both of the association tables.
+           */
+
+        Set indKeySet = indirectionTables.keySet();
+        Iterator indKeysItr = indKeySet.iterator();
+        while(indKeysItr.hasNext())
+        {
+            String tableName = (String) indKeysItr.next();
+
+            /*
+                *	Sometimes there can be explicit mappings for indirection tables. In such cases
+                *	skip the auto generation of indirection table.
+                */
+            if(allTables.contains(tableName))
+                continue;
+
+            Table indirectionTable = (Table) indirectionTables.get(tableName);
+
+            String tableStr = TorqueSchemaGenerator.generateTorqueSchema(indirectionTable);
+            fwr.write(tableStr);
+        }
+
+        fwr.write(TorqueSchemaGenerator.torqueSuffix());
+        fwr.close();
+    }
+
+    /** Generate the source for Java beans mapped to tables. */
+    public void generateJavaCode() throws Exception
+    {
+        NodeList clsDescList = doc.getElementsByTagName("class-descriptor");
+        for(int i = 0; i < clsDescList.getLength(); i++)
+        {
+            Element clsDescElem = (Element) clsDescList.item(i);
+
+            String clsName = clsDescElem.getAttribute("class");
+
+            String packageName = null;
+            String className;
+            int indexDot = clsName.lastIndexOf(".");
+            if(indexDot == -1)
+                className = clsName;
+            else
+            {
+                packageName = clsName.substring(0, indexDot);
+                className = clsName.substring(indexDot + 1);
+            }
+
+            String baseClass = null;
+            ArrayList attributes = new ArrayList();
+            ArrayList types = new ArrayList();
+
+            NodeList refDescList = clsDescElem.getElementsByTagName("reference-descriptor");
+            for(int j = 0; j < refDescList.getLength(); j++)
+            {
+                Element refDescElem = (Element) refDescList.item(j);
+
+                String fieldName = refDescElem.getAttribute("name");
+                String classRef = refDescElem.getAttribute("class-ref");
+
+                // handle super references
+                if(fieldName.equals("super"))
+                {
+                    baseClass = classRef;
+                }
+                else
+                {
+                    attributes.add(fieldName);
+                    types.add(classRef);
+                }
+            }
+
+            NodeList fldDescList = clsDescElem.getElementsByTagName("field-descriptor");
+            for(int j = 0; j < fldDescList.getLength(); j++)
+            {
+                Element fldDescElem = (Element) fldDescList.item(j);
+
+                String fieldName = fldDescElem.getAttribute("name");
+                String jdbcType = fldDescElem.getAttribute("jdbc-type");
+                String primaryKey = fldDescElem.getAttribute("primarykey");
+                boolean isPrimaryKey = primaryKey != null && primaryKey.equals("true");
+                String type = (String) typeMap.get(jdbcType);
+
+                /*
+                     *	If baseClass is set using the 'super' reference then primary key
+                     *	fields are being repeated only for join purpose.
+                     */
+                if(baseClass == null || !isPrimaryKey)
+                {
+                    attributes.add(fieldName);
+                    types.add(type);
+                }
+            }
+
+            NodeList colDescList = clsDescElem.getElementsByTagName("collection-descriptor");
+            for(int j = 0; j < colDescList.getLength(); j++)
+            {
+                Element colDescElem = (Element) colDescList.item(j);
+
+                String fieldName = colDescElem.getAttribute("name");
+                String type = "java.util.List";
+
+                attributes.add(fieldName);
+                types.add(type);
+            }
+
+            BeanDescriptor descriptor = new BeanDescriptor(packageName, className, baseClass, null,
+                    attributes, types);
+            BeanGenerator generator = new BeanGenerator(beanOutputDirectory);
+            generator.generate(descriptor);
+        }
+    }
+
+    Element findClass(Document doc, String name)
+    {
+        NodeList clsDescList = doc.getElementsByTagName("class-descriptor");
+        for(int j = 0; j < clsDescList.getLength(); j++)
+        {
+            Element elem = (Element) clsDescList.item(j);
+            String clsName = elem.getAttribute("class");
+            if(clsName != null && clsName.equals(name))
+            {
+                return elem;
+            }
+        }
+        return null;
+    }
+
+    Element findFirstMappedClass(Document doc, String name)
+    {
+        Element result = findClass(doc, name);
+        String tablename = result.getAttribute("table");
+        if(StringUtils.isEmpty(tablename))
+        {
+            String[] subClasses = findDeclaredExtendClasses(result);
+            for(int i = 0; i < subClasses.length; i++)
+            {
+                String className = subClasses[i];
+                result = findFirstMappedClass(doc, className);
+            }
+        }
+        return result;
+    }
+
+    String[] findDeclaredExtendClasses(Element classNode)
+    {
+        List result = new ArrayList();
+        NodeList list = classNode.getElementsByTagName("extent-class");
+        for(int i = 0; i < list.getLength(); i++)
+        {
+            Element e = (Element) list.item(i);
+            String refClass = e.getAttribute("class-ref");
+            if(refClass != null)
+            {
+                result.add(refClass);
+            }
+        }
+        return (String[]) result.toArray(new String[result.size()]);
+    }
+
+    class ForwardException extends RuntimeException
+    {
+        public ForwardException()
+        {
+        }
+
+        public ForwardException(String message)
+        {
+            super(message);
+        }
+
+        public ForwardException(Throwable cause)
+        {
+            super(cause);
+        }
+
+        public ForwardException(String message, Throwable cause)
+        {
+            super(message, cause);
+        }
+    }
+
+    public static void main(String [] args) throws Exception
+    {
+        RepositoryXmlProcessor processor = new RepositoryXmlProcessor
+                ("repository.xml", "target/test", "target/test");
+//        RepositoryXmlProcessor processor = new RepositoryXmlProcessor
+//                ("repository.xml", "target/test", "target/test");
+        processor.generateSQL();
+        processor.generateJavaCode();
+    }
+}
\ No newline at end of file

Added: db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/SQLStructures.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/SQLStructures.java?rev=424221&view=auto
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/SQLStructures.java (added)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/SQLStructures.java Fri Jul 21 00:55:21 2006
@@ -0,0 +1,154 @@
+package org.apache.ojb.tools.mapping.forward;
+
+/* Copyright 2002-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
+/*
+ *	Classes for representing SQL schema structures. The representation maps to OJB's
+ *	repository.xml format whereever there is a mismatch between OJB format and the Torque
+ *	format. For example in repository.xml, uniqueness of columns can be represented only
+ *	by using a 'unique' attribute of the index descriptor, whereas in the Torque schema
+ *	these are seperate aspects. The transformation will be handled in the TorqueSchemaGenerator.
+ */
+
+/**
+ * Structure representing a Table.
+ *
+ * @author Tom Antony
+ * @version 1.0, 03-MAY-2006.
+ */
+class Table
+{
+    String name;
+
+    ArrayList columns = new ArrayList();
+    ArrayList foreignKeys = new ArrayList();
+    ArrayList indexes = new ArrayList();
+
+    public boolean equals(Object o)
+    {
+        if(o == null || !(o instanceof Table))
+            return false;
+
+        Table other = (Table) o;
+        return other.name != null && other.name.equals(name);
+    }
+
+    public String toString()
+    {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}
+
+/**
+ * Structure representing a column.
+ *
+ * @author Tom Antony
+ * @version 1.0, 03-MAY-2006.
+ */
+class Column
+{
+    String name;
+
+    boolean isPrimaryKey;
+    boolean isNullable = true;    // OJB default.
+    boolean isAutoIncriment;
+
+    String jdbcType;
+    String length;
+
+    public boolean equals(Object o)
+    {
+        if(o == null || !(o instanceof Column))
+            return false;
+
+        Column other = (Column) o;
+        return other.name != null && other.name.equals(name);
+    }
+
+    public String toString()
+    {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}
+
+/**
+ * Structure representing a foreign key.
+ *
+ * @author Tom Antony
+ * @version 1.0, 03-MAY-2006.
+ */
+class ForeignKey
+{
+    String foreignTable;
+    ArrayList localColumns = new ArrayList();
+    ArrayList foreignColumns = new ArrayList();
+
+    public boolean equals(Object o)
+    {
+        if(o == null || !(o instanceof ForeignKey))
+            return false;
+
+        ForeignKey other = (ForeignKey) o;
+
+        if(foreignTable.equals(other.foreignTable))
+        {
+            if(Utils.compareLists(localColumns, other.localColumns))
+                return Utils.compareLists(foreignColumns, other.foreignColumns);
+            else
+                return false;
+        }
+        else
+            return false;
+    }
+
+    public String toString()
+    {
+        return ToStringBuilder.reflectionToString(this);
+    }
+}
+
+/**
+ * Structure representing an index.
+ *
+ * @author Tom Antony
+ * @version 1.0, 03-MAY-2006.
+ */
+class Index
+{
+    String name;
+    boolean isUnique;
+    ArrayList columns = new ArrayList();
+
+    public boolean equals(Object o)
+    {
+        if(o == null || !(o instanceof Index))
+            return false;
+
+        Index other = (Index) o;
+
+        return Utils.compareLists(columns, other.columns);
+    }
+
+    public String toString()
+    {
+        return ToStringBuilder.reflectionToString(this);
+    }
+}

Added: db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/TorqueSchemaGenerator.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/TorqueSchemaGenerator.java?rev=424221&view=auto
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/TorqueSchemaGenerator.java (added)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/TorqueSchemaGenerator.java Fri Jul 21 00:55:21 2006
@@ -0,0 +1,207 @@
+package org.apache.ojb.tools.mapping.forward;
+
+/* Copyright 2002-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Generator for Torque format database schema definitions.
+ *
+ * @author Tom Antony
+ * @version 1.0, 03-MAY-2006.
+ */
+public class TorqueSchemaGenerator
+{
+    private static String SPACE = " ";
+    private static String TAB = "\t";
+    private static String NEWLINE = System.getProperty("line.separator");
+
+    /**
+     * The prefix string for Torque xml.
+     *
+     * @return the prefix string
+     */
+    public static String torquePrefix()
+    {
+        StringBuffer buf = new StringBuffer(150);
+
+        buf.append("<?xml version=\"1.0\"?>");
+        buf.append(whitespace(NEWLINE, 1));
+        buf.append("<!DOCTYPE database SYSTEM \"http://db.apache.org/torque/dtd/database.dtd\">");
+        buf.append(whitespace(NEWLINE, 2));
+        buf.append("<database name=\"ojb-auto-gen\">");
+
+        return buf.toString();
+    }
+
+    /**
+     * The suffix string for Torque xml.
+     *
+     * @return the suffix string
+     */
+    public static String torqueSuffix()
+    {
+        return whitespace(NEWLINE, 2) + "</database>";
+    }
+
+    private static String whitespace(String ch, int num)
+    {
+        String str = "";
+        for(int i = 0; i < num; i++)
+            str += ch;
+        return str;
+    }
+
+    /*
+      *	Generate the <table> xml block corresponding to the Table structure.
+      *
+      *	@param table the Table structure
+      *	@return the Torque xml table definition.
+      */
+    public static String generateTorqueSchema(Table table)
+    {
+        StringBuffer buf = new StringBuffer(100);
+
+        buf.append(whitespace(NEWLINE, 2));
+        buf.append(whitespace(TAB, 1));
+
+        buf.append("<table name=\"").append(table.name).append("\">");
+
+        // generate column definitions.
+        for(int i = 0; i < table.columns.size(); i++)
+        {
+            Column column = (Column) table.columns.get(i);
+
+            buf.append(whitespace(NEWLINE, 1));
+            buf.append(whitespace(TAB, 2));
+
+            buf.append("<column ");
+
+            buf.append(whitespace(NEWLINE, 1));
+            buf.append(whitespace(TAB, 2));
+            buf.append(whitespace(SPACE, 3));
+            buf.append("name=\"").append(column.name).append("\"");
+
+            buf.append(whitespace(NEWLINE, 1));
+            buf.append(whitespace(TAB, 2));
+            buf.append(whitespace(SPACE, 3));
+            buf.append("type=\"").append(column.jdbcType).append("\"");
+
+            if(column.length != null && column.length.trim().length() > 0)
+            {
+                buf.append(whitespace(NEWLINE, 1));
+                buf.append(whitespace(TAB, 2));
+                buf.append(whitespace(SPACE, 3));
+                buf.append("size=\"").append(column.length).append("\"");
+            }
+            if(column.isPrimaryKey)
+            {
+                buf.append(whitespace(NEWLINE, 1));
+                buf.append(whitespace(TAB, 2));
+                buf.append(whitespace(SPACE, 3));
+                buf.append("primaryKey=\"true\"");
+            }
+            if(!column.isNullable)
+            {
+                buf.append(whitespace(NEWLINE, 1));
+                buf.append(whitespace(TAB, 2));
+                buf.append(whitespace(SPACE, 3));
+                buf.append("required=\"true\"");
+            }
+            if(column.isAutoIncriment)
+            {
+                buf.append(whitespace(NEWLINE, 1));
+                buf.append(whitespace(TAB, 2));
+                buf.append(whitespace(SPACE, 3));
+                buf.append("autoIncrement=\"true\"");
+            }
+
+            buf.append("/>");
+        }
+
+        // generate foreign key definitions.
+        for(int i = 0; i < table.foreignKeys.size(); i++)
+        {
+            ForeignKey foreignKey = (ForeignKey) table.foreignKeys.get(i);
+
+            buf.append(whitespace(NEWLINE, 1));
+            buf.append(whitespace(TAB, 2));
+            buf.append("<foreign-key foreignTable=\"").append(foreignKey.foreignTable).append("\">");
+
+            for(int j = 0; j < foreignKey.localColumns.size(); j++)
+            {
+                String localColumn = (String) foreignKey.localColumns.get(j);
+                String foreignColumn = (String) foreignKey.foreignColumns.get(j);
+
+                buf.append(whitespace(NEWLINE, 1));
+                buf.append(whitespace(TAB, 3));
+                buf.append("<reference local=\"")
+                        .append(localColumn).append("\" foreign=\"").append(foreignColumn).append("\"/>");
+            }
+
+            buf.append(whitespace(NEWLINE, 1));
+            buf.append(whitespace(TAB, 2));
+            buf.append("</foreign-key>");
+        }
+
+        // generate index definitions.
+        for(int i = 0; i < table.indexes.size(); i++)
+        {
+            Index index = (Index) table.indexes.get(i);
+
+            buf.append(whitespace(NEWLINE, 1));
+            buf.append(whitespace(TAB, 2));
+            buf.append("<index name=\"").append(index.name).append("\">");
+
+            for(int j = 0; j < index.columns.size(); j++)
+            {
+                buf.append(whitespace(NEWLINE, 1));
+                buf.append(whitespace(TAB, 3));
+                buf.append("<index-column name=\"").append(index.columns.get(j)).append("\"/>");
+            }
+
+            buf.append(whitespace(NEWLINE, 1));
+            buf.append(whitespace(TAB, 2));
+            buf.append("</index>");
+        }
+
+        // generate unique constraint definitions.
+        for(int i = 0; i < table.indexes.size(); i++)
+        {
+            Index index = (Index) table.indexes.get(i);
+
+            if(index.isUnique)
+            {
+                buf.append(whitespace(NEWLINE, 1));
+                buf.append(whitespace(TAB, 2));
+                buf.append("<unique>");
+                for(int j = 0; j < index.columns.size(); j++)
+                {
+                    buf.append(whitespace(NEWLINE, 1));
+                    buf.append(whitespace(TAB, 3));
+                    buf.append("<unique-column name=\"").append(index.columns.get(j)).append("\"/>");
+                }
+                buf.append(whitespace(NEWLINE, 1));
+                buf.append(whitespace(TAB, 2));
+                buf.append("</unique>");
+            }
+        }
+
+        buf.append(whitespace(NEWLINE, 1));
+        buf.append(whitespace(TAB, 1));
+        buf.append("</table>");
+
+        return buf.toString();
+	}
+}
\ No newline at end of file

Added: db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/Utils.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/Utils.java?rev=424221&view=auto
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/Utils.java (added)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/tools/org/apache/ojb/tools/mapping/forward/Utils.java Fri Jul 21 00:55:21 2006
@@ -0,0 +1,62 @@
+package org.apache.ojb.tools.mapping.forward;
+
+/* Copyright 2002-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+
+/**
+ * Utility functions.
+ *
+ * @author Tom Antony
+ * @version 1.0, 03-MAY-2006.
+ */
+public class Utils
+{
+    /*
+      *	Compare two lists in an order independent manner.
+      *
+      *	Note : the contains() method of the Collections interface will use the equals() method
+      *	of Object class to determine equalness. So elements in source and target should have
+      *	equals() method properly defined.
+      *
+      *	@param src the source list
+      *	@param target the target list
+      *	@return true if lists contain the same set of elements, else false.
+      */
+    public static boolean compareLists(List src, List target)
+    {
+        if(src == null && target == null) return true;
+        if((src != null && target == null) || (src == null && target != null)) return false;
+        if(src.size() != target.size()) return false;
+
+        // Each item in source should be present in target.
+        for(int k = 0; k < src.size(); k++)
+        {
+            Object item = src.get(k);
+            if(!target.contains(item)) return false;
+        }
+
+        // Each item in target should be present in source.
+        for(int k = 0; k < target.size(); k++)
+        {
+            Object item = target.get(k);
+            if(!src.contains(item)) return false;
+        }
+
+        return true;
+    }
+
+}
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org