Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

DatabaseSchema.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2004 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Emmanuel Cecchet.
00022  * Contributor(s): ______________________________________.
00023  */
00024 
00025 package org.objectweb.cjdbc.common.sql.schema;
00026 
00027 import java.io.Serializable;
00028 import java.sql.SQLException;
00029 import java.util.ArrayList;
00030 
00031 import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
00032 
00033 /**
00034  * A <code>DatabaseSchema</code> describes all the tables and columns of a
00035  * database.
00036  * 
00037  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00038  * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
00039  * @version 1.0
00040  */
00041 public class DatabaseSchema implements Serializable
00042 {
00043   /** <code>ArrayList</code> of <code>DatabaseTables</code>. */
00044   private ArrayList tables;
00045   /** <code>ArrayList</code> of <code>DatabaseProcedures</code>. */
00046   private ArrayList procedures;
00047 
00048   /**
00049    * Creates a new <code>DatabaseSchema</code> instance.
00050    */
00051   public DatabaseSchema()
00052   {
00053     tables = new ArrayList();
00054     procedures = new ArrayList();
00055   }
00056 
00057   /**
00058    * Creates a new <code>DatabaseSchema</code> instance with a specified
00059    * number of tables.
00060    * 
00061    * @param nbOfTables an <code>int</code> value
00062    */
00063   public DatabaseSchema(int nbOfTables)
00064   {
00065     tables = new ArrayList(nbOfTables);
00066     procedures = new ArrayList();
00067   }
00068 
00069   /**
00070    * Creates a new <code>DatabaseSchema</code> instance from an existing
00071    * database schema (the schema is cloned).
00072    * 
00073    * @param schema the existing database schema
00074    */
00075   public DatabaseSchema(DatabaseSchema schema)
00076   {
00077     if (schema == null)
00078       throw new IllegalArgumentException(
00079           "Illegal null database schema in DatabaseSchema(DatabaseSchema) constructor");
00080 
00081     tables = new ArrayList(schema.getTables());
00082     procedures = new ArrayList(schema.getProcedures());
00083   }
00084 
00085   /**
00086    * Adds a <code>DatabaseTable</code> describing a table of the database.
00087    * 
00088    * @param table the table to add
00089    */
00090   public void addTable(DatabaseTable table)
00091   {
00092     if (table == null)
00093       throw new IllegalArgumentException(
00094           "Illegal null database table in addTable(DatabaseTable) method");
00095     tables.add(table);
00096   }
00097 
00098   /**
00099    * Adds a <code>DatabaseProcedure</code> describing a procedure of the
00100    * database.
00101    * 
00102    * @param procedure the procedure to add
00103    */
00104   public void addProcedure(DatabaseProcedure procedure)
00105   {
00106     if (procedure == null)
00107       throw new IllegalArgumentException(
00108           "Illegal null database table in addTable(DatabaseTable) method");
00109     procedures.add(procedure);
00110   }
00111 
00112   /**
00113    * Removes a <code>DatabaseTable</code> describing a table of the database.
00114    * 
00115    * @param table the table to remove
00116    */
00117   public void removeTable(DatabaseTable table)
00118   {
00119     if (table == null)
00120       throw new IllegalArgumentException(
00121           "Illegal null database table in removeTable(DatabaseTable) method");
00122     tables.remove(table);
00123   }
00124 
00125   /**
00126    * removes a <code>DatabaseProcedure</code> describing a procedure of the
00127    * database.
00128    * 
00129    * @param procedure to remove
00130    */
00131   public void removeProcedure(DatabaseProcedure procedure)
00132   {
00133     if (procedure == null)
00134       throw new IllegalArgumentException(
00135           "Illegal null database procedure in removeProcedure(DatabaseProcedure) method");
00136     procedures.remove(procedure);
00137   }
00138 
00139   /**
00140    * Merges the given schema with the current one. All missing tables or columns
00141    * are added if no conflict is detected. An exception is thrown if the given
00142    * schema definition conflicts with the current one.
00143    * 
00144    * @param databaseSchema the schema to merge
00145    * @throws SQLException if the schemas conflict
00146    */
00147   public void mergeSchema(DatabaseSchema databaseSchema) throws SQLException
00148   {
00149     if (databaseSchema == null)
00150       throw new IllegalArgumentException(
00151           "Illegal null database schema in mergeSchema(DatabaseSchema) method");
00152 
00153     ArrayList otherTables = databaseSchema.getTables();
00154     if (otherTables.size() == 0)
00155       return;
00156 
00157     DatabaseTable table, originalTable;
00158     int size = otherTables.size();
00159     for (int i = 0; i < size; i++)
00160     {
00161       table = (DatabaseTable) otherTables.get(i);
00162       originalTable = getTable(table.getName());
00163       if (originalTable == null)
00164         addTable(table);
00165       else
00166         originalTable.mergeColumns(table);
00167     }
00168 
00169     ArrayList otherProcedures = databaseSchema.getProcedures();
00170     if (otherProcedures.size() == 0)
00171       return;
00172 
00173     DatabaseProcedure procedure, originalProcedure;
00174     int sizep = otherProcedures.size();
00175     for (int i = 0; i < sizep; i++)
00176     {
00177       procedure = (DatabaseProcedure) otherProcedures.get(i);
00178       originalProcedure = getProcedure(procedure.getName());
00179       if (originalProcedure == null)
00180         addProcedure(procedure);
00181       else
00182         originalProcedure.mergeParameters(procedure);
00183     }
00184   }
00185 
00186   /**
00187    * Returns an <code>ArrayList</code> of <code>DatabaseTable</code> objects
00188    * describing the database.
00189    * 
00190    * @return an <code>ArrayList</code> of <code>DatabaseTable</code>
00191    */
00192   public ArrayList getTables()
00193   {
00194     return tables;
00195   }
00196 
00197   /**
00198    * Returns an <code>ArrayList</code> of <code>DatabaseProcedure</code>
00199    * objects describing the database.
00200    * 
00201    * @return an <code>ArrayList</code> of <code>DatabaseProcedure</code>
00202    */
00203   public ArrayList getProcedures()
00204   {
00205     return procedures;
00206   }
00207 
00208   /**
00209    * Returns the <code>DatabaseTable</code> object matching the given table
00210    * name or <code>null</code> if not found.
00211    * 
00212    * @param tableName the table name to look for
00213    * @return a <code>DatabaseTable</code> value or null
00214    */
00215   public DatabaseTable getTable(String tableName)
00216   {
00217     if (tableName == null)
00218       return null;
00219 
00220     DatabaseTable t;
00221     int size = tables.size();
00222     for (int i = 0; i < size; i++)
00223     {
00224       t = (DatabaseTable) tables.get(i);
00225       if (tableName.compareTo(t.getName()) == 0)
00226         return t;
00227     }
00228     return null;
00229   }
00230 
00231   /**
00232    * Returns the <code>DatabaseProcedure</code> object matching the given
00233    * procedure name or <code>null</code> if not found.
00234    * 
00235    * @param procedureName the procedure name to look for
00236    * @return a <code>DatabaseProcedure</code> value or null
00237    */
00238   public DatabaseProcedure getProcedure(String procedureName)
00239   {
00240     if (procedureName == null)
00241       return null;
00242 
00243     DatabaseProcedure t;
00244     int size = procedures.size();
00245     for (int i = 0; i < size; i++)
00246     {
00247       t = (DatabaseProcedure) procedures.get(i);
00248       if (procedureName.compareTo(t.getName()) == 0)
00249         return t;
00250     }
00251     return null;
00252   }
00253 
00254   /**
00255    * Returns the <code>DatabaseTable</code> object matching the given table
00256    * name or <code>null</code> if not found. An extra boolean indicates if
00257    * table name matching is case sensitive or not.
00258    * 
00259    * @param tableName the table name to look for
00260    * @param isCaseSensitive true if name matching must be case sensitive
00261    * @return a <code>DatabaseTable</code> value or null
00262    */
00263   public DatabaseTable getTable(String tableName, boolean isCaseSensitive)
00264   {
00265     if (isCaseSensitive)
00266       return getTable(tableName);
00267 
00268     if (tableName == null)
00269       return null;
00270 
00271     DatabaseTable t;
00272     int size = tables.size();
00273     for (int i = 0; i < size; i++)
00274     {
00275       t = (DatabaseTable) tables.get(i);
00276       if (tableName.equalsIgnoreCase(t.getName()))
00277         return t;
00278     }
00279     return null;
00280   }
00281 
00282   /**
00283    * Returns <code>true</code> if the given <code>TableName</code> is found
00284    * in this schema.
00285    * 
00286    * @param tableName the name of the table you are looking for
00287    * @return <code>true</code> if the table has been found
00288    */
00289   public boolean hasTable(String tableName)
00290   {
00291     if (tableName == null)
00292       return false;
00293 
00294     DatabaseTable t;
00295     int size = tables.size();
00296     for (int i = 0; i < size; i++)
00297     {
00298       t = (DatabaseTable) tables.get(i);
00299       if (tableName.equals(t.getName()))
00300         return true;
00301     }
00302     return false;
00303   }
00304 
00305   /**
00306    * Returns <code>true</code> if the given <code>ProcedureName</code> is
00307    * found in this schema.
00308    * 
00309    * @param procedureName the name of the procedure you are looking for
00310    * @return <code>true</code> if the procedure has been found
00311    */
00312   public boolean hasProcedure(String procedureName)
00313   {
00314     if (procedureName == null)
00315       return false;
00316 
00317     DatabaseProcedure t;
00318     int size = procedures.size();
00319     for (int i = 0; i < size; i++)
00320     {
00321       t = (DatabaseProcedure) procedures.get(i);
00322       if (procedureName.equals(t.getName()))
00323         return true;
00324     }
00325     return false;
00326   }
00327 
00328   /**
00329    * Checks if this <code>DatabaseSchema</code> is a compatible subset of a
00330    * given schema. It means that all tables in this schema must be present with
00331    * the same definition in the other schema.
00332    * 
00333    * @param other the object to compare with
00334    * @return <code>true</code> if the two schemas are compatible
00335    */
00336   public boolean isCompatibleSubset(DatabaseSchema other)
00337   {
00338     if (other == null)
00339       return false;
00340 
00341     DatabaseTable table, otherTable;
00342     int size = tables.size();
00343     for (int i = 0; i < size; i++)
00344     {
00345       // Parse all tables
00346       table = (DatabaseTable) tables.get(i);
00347       otherTable = other.getTable(table.getName());
00348       if (otherTable == null)
00349         return false; // Not present
00350       else if (!table.equalsIgnoreType(otherTable))
00351         return false; // Not compatible
00352     }
00353     DatabaseProcedure procedure, otherProcedure;
00354     int sizep = procedures.size();
00355     for (int i = 0; i < sizep; i++)
00356     {
00357       // Parse all procedures
00358       procedure = (DatabaseProcedure) procedures.get(i);
00359       otherProcedure = other.getProcedure(procedure.getName());
00360       if (otherProcedure == null)
00361         return false; // Not present
00362       else if (!procedure.equals(otherProcedure))
00363         return false; // Not compatible
00364     }
00365     return true; // Ok, all tables passed the test
00366   }
00367 
00368   /**
00369    * Checks if this <code>DatabaseSchema</code> is compatible with the given
00370    * schema. It means that all tables in this schema that are common with the
00371    * other schema must be identical.
00372    * 
00373    * @param other the object to compare with
00374    * @return <code>true</code> if the two schemas are compatible
00375    */
00376   public boolean isCompatibleWith(DatabaseSchema other)
00377   {
00378     DatabaseTable table, otherTable;
00379     int size = tables.size();
00380     for (int i = 0; i < size; i++)
00381     { // Parse all tables
00382       table = (DatabaseTable) tables.get(i);
00383       otherTable = other.getTable(table.getName());
00384       if (otherTable == null)
00385         continue; // Not present in other schema
00386       else if (!table.equalsIgnoreType(otherTable))
00387         return false; // Not compatible
00388     }
00389     DatabaseProcedure procedure, otherProcedure;
00390     int sizep = procedures.size();
00391     for (int i = 0; i < sizep; i++)
00392     { // Parse all procedures
00393       procedure = (DatabaseProcedure) procedures.get(i);
00394       otherProcedure = other.getProcedure(procedure.getName());
00395       if (otherProcedure == null)
00396         continue; // Not present
00397       else if (!procedure.equals(otherProcedure))
00398         return false; // Not compatible
00399     }
00400     return true; // Ok, all tables passed the test
00401   }
00402 
00403   /**
00404    * Two <code>DatabaseSchema</code> are considered equal if they have the
00405    * same tables and the same procedures.
00406    * 
00407    * @param other the object to compare with
00408    * @return <code>true</code> if the schemas are equals
00409    */
00410   public boolean equals(Object other)
00411   {
00412     boolean equal = true;
00413     if ((other == null) || !(other instanceof DatabaseSchema))
00414       return false;
00415     if (tables == null)
00416       equal &= ((DatabaseSchema) other).getTables() == null;
00417     else
00418       equal &= tables.equals(((DatabaseSchema) other).getTables());
00419     if (procedures == null)
00420       equal &= ((DatabaseSchema) other).getProcedures() == null;
00421     else
00422       equal &= procedures.equals(((DatabaseSchema) other).getProcedures());
00423     return equal;
00424   }
00425 
00426   /**
00427    * Get xml information about this schema.
00428    * 
00429    * @return xml formatted information on this database schema.
00430    */
00431   public String getXml()
00432   {
00433     StringBuffer info = new StringBuffer();
00434     info.append("<" + DatabasesXmlTags.ELT_DatabaseStaticSchema + ">");
00435     for (int i = 0; i < procedures.size(); i++)
00436       info.append(((DatabaseProcedure) procedures.get(i)).getXml());
00437     for (int i = 0; i < tables.size(); i++)
00438       info.append(((DatabaseTable) tables.get(i)).getXml());
00439     info.append("</" + DatabasesXmlTags.ELT_DatabaseStaticSchema + ">");
00440     return info.toString();
00441   }
00442 
00443 }

Generated on Mon Apr 11 22:01:31 2005 for C-JDBC by  doxygen 1.3.9.1