All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.empire.db.DBTable Maven / Gradle / Ivy

There is a newer version: 3.3.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package org.apache.empire.db;

// java
import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.empire.data.DataMode;
import org.apache.empire.data.DataType;
import org.apache.empire.db.DBRelation.DBCascadeAction;
import org.apache.empire.db.exceptions.NoPrimaryKeyException;
import org.apache.empire.db.exceptions.RecordDeleteFailedException;
import org.apache.empire.db.exceptions.RecordUpdateInvalidException;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.ItemExistsException;
import org.apache.empire.exceptions.UnexpectedReturnValueException;


/**
 * This class represent one table of the database.
 * It contains methods to get, add, update and delete records from the database.
 * 

* * */ public class DBTable extends DBRowSet implements Cloneable { // Integer size definitions public static final int DEFAULT = 0; public static final int SMALLINT = 2; public static final int MEDIUMINT = 4; public static final int BIGINT = 8; private final static long serialVersionUID = 1L; private static AtomicInteger tableCount = new AtomicInteger(0); private final String name; private String alias; private final List indexes = new ArrayList(); private Boolean quoteName = null; private DBCascadeAction cascadeDeleteAction = DBCascadeAction.NONE; /** * Construct a new DBTable object set the specified parameters * to this object and add this object to the current database. * * @param name the table name * @param db the valid database object */ public DBTable(String name, DBDatabase db) { super(db); // init this.name = name; this.alias = "t" + String.valueOf(tableCount.incrementAndGet()); // Add Table to Database if (db != null) db.addTable(this); } /** * Returns the table name of this object. * * @return the table name of this object */ @Override public String getName() { return name; } /** * Returns the table alias name of this object. * * @return the table alias name of this object */ @Override public String getAlias() { return alias; } /** * Returns whether or not the table supports record updates. Default is true. * @return true if the table allows record updates */ @Override public boolean isUpdateable() { return true; } /** * Clones this table and assigns a new table alias. * This second instance of the same table can be used for self-joins. *

     * This method requires that all declared column fields are NOT declared final.

* i.e. instead of: * * public final DBTableColumn MYCOL; * * columns must be declared: * * public DBTableColumn MYCOL; * * A runtime exception for the CloneNotSupported will be thrown if references cannot be adjusted. * * Alternatively a second table instance may be created manually like this: * * public final MyTable MYTABLE1 = new MyTable(); * public final MyTable MYTABLE2 = new MyTable(); * * ... * cmd.join(MYTABLE1.ID, MYTABLE2.PARENTID); // self-join * ... *
     * @return a table clone with new table alias
     */
    @Override
    public Object clone()
    {
        try {
            DBTable clone = (DBTable) super.clone();
            // clone all columns
            Class colClass = columns.get(0).getClass();
            Class colBase = colClass.getSuperclass();
            clone.columns = new ArrayList();
            Field[] fields = getClass().getFields();
            for (int i = 0; i < columns.size(); i++)
            {
                DBTableColumn srcCol = (DBTableColumn) columns.get(i);
                DBTableColumn newCol = new DBTableColumn(clone, srcCol);
                // Replace all references for oldCol to newCol
                for (int j = 0; j < fields.length; j++)
                { // Find a class of Type DBColumn or DBTableColumn
                    Class type = fields[j].getType();
                    if (type == colClass || type == colBase)
                    {
                        try
                        {   // Check if the field points to the old Value
                            if (fields[j].get(clone) == srcCol)
                              fields[j].set(clone, newCol);
                        } catch (Exception e)  {
                            // IllegalAccessException or IllegalArgumentException
                            String fieldName = fields[j].getName();
                            log.error("Cannot adjust declared table field: " + fieldName + ". Reason is: " + e.getMessage());
                            // throw CloneNotSupportedException
                            CloneNotSupportedException cnse = new CloneNotSupportedException("Unable to replace field reference for field " + fieldName);
                            cnse.initCause(e);
                            throw cnse;
                        }
                    }
                }
            }
            // set new alias
            clone.alias = "t" + String.valueOf(tableCount.incrementAndGet());
            // done
            log.info("clone: Table " + name + " cloned! Alias old=" + alias + " new=" + clone.alias);
            return clone;

        } catch (CloneNotSupportedException e) {
            // unable to clone table
            log.error("Unable to clone table " + getName());
            throw new RuntimeException(e);
        }
    }

    /**
     * Adds a column to this table's column list.
     * 
     * @param column a column object
     */
    protected void addColumn(DBTableColumn column)
    { // find column by name
        if (column==null || column.getRowSet()!=this)
            throw new InvalidArgumentException("column", column);
        if (getColumn(column.getName())!=null)
            throw new ItemExistsException(column.getName());
        // add now
        columns.add(column);
    }

    /**
     * Creates a new DBTableColumn object and adds it to the column collection.
     * 
     * @param columnName the column name
     * @param type the type of the column e.g. integer, text, date
     * @param size the column width
     * @param dataMode determines whether this column is optional, required or auto-generated 
     * @param defValue a Object object
     * @return the created DBTableColumn object
     */
    public final DBTableColumn addColumn(String columnName, DataType type, double size, DataMode dataMode, Object defValue)
    { 
        return new DBTableColumn(this, type, columnName, size, dataMode, defValue);
    }

    /**
     * Creates a new DBTableColumn object and adds it to the column collection.
     * 
     * @param columnName the column name
     * @param type the type of the column e.g. integer, text, date
     * @param size the column width
     * @param dataMode determines whether this column is optional, required or auto-generated 
     * @return the created DBTableColumn object
     */
    public final DBTableColumn addColumn(String columnName, DataType type, double size, DataMode dataMode)
    { 
        return new DBTableColumn(this, type, columnName, size, dataMode, null);
    }

    /**
     * Creates a new DBTableColumn object and adds it to the column collection.
     * Instead of the data mode enum, a boolean flag is used to indicate whether the column is required or optional.
     * 
     * @param columnName the column name
     * @param type the type of the column e.g. integer, text, date
     * @param size the column width
     * @param required true if not null column
     * @param defValue a Object object
     * @return the created DBTableColumn object
     */
    public final DBTableColumn addColumn(String columnName, DataType type, double size, boolean required, Object defValue)
    { 
        DataMode dm = (required ? DataMode.NotNull : DataMode.Nullable);
        return new DBTableColumn(this, type, columnName, size, dm, defValue);
    }

    /**
     * Creates a new DBTableColumn object and adds it to the column collection.
     * Instead of the data mode enum, a boolean flag is used to indicate whether the column is required or optional. 
     * 
     * @param columnName the column name
     * @param type the type of the column e.g. integer, text, date
     * @param size the column width
     * @param required true if not null column
     * @return the created DBTableColumn object
     */
    public final DBTableColumn addColumn(String columnName, DataType type, double size, boolean required)
    { 
        DataMode dm = (required ? DataMode.NotNull : DataMode.Nullable);
        return new DBTableColumn(this, type, columnName, size, dm, null);
    }

    /**
     * Returns the primary key.
     * 
     * @return the the DBIndex object ->primary key
     */
    public DBIndex getPrimaryKey()
    {
        return primaryKey;
    }

    /**
     * Returns the list of indexes (except the primary key).
     * 
     * @return a list of DBIndex objects
     */
    public List getIndexes()
    {
        return indexes;
    }
    
    /**
     * Sets the primary keys.
     * 
     * @param columns a array with one or more DBColumn objects
     */
    public void setPrimaryKey(DBColumn... columns)
    {
        if (columns==null || columns.length==0)
            throw new InvalidArgumentException("columns", columns);
        // All columns must belong to this table
        for (int i=0; i 1)
        { // Multiple Records affected
            throw new RecordUpdateInvalidException(this, key);
        }
    }
    
    /**
     * Returns a list of all foreign key relations for this table
     * @return the list of foreign key relations
     */
    public List getForeignKeyRelations()
    {
        List relations = new ArrayList();
        for (DBRelation r : getDatabase().getRelations())
        {   // check relation
            if (this.equals(r.getForeignKeyTable()))
                relations.add(r);
        }
        return relations;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy