com.xdev.jadoth.sqlengine.internal.tables.SqlDdlTable Maven / Gradle / Ivy
/*
* XDEV Application Framework - XDEV Application Framework
* Copyright © 2003 XDEV Software (https://xdev.software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
package com.xdev.jadoth.sqlengine.internal.tables;
import static com.xdev.jadoth.sqlengine.SQL.LANG.CREATE_TABLE;
import static com.xdev.jadoth.sqlengine.SQL.LANG.DEFAULT;
import static com.xdev.jadoth.sqlengine.SQL.LANG.DROP_TABLE;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.NEW_LINE;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.TAB;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation._;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.comma_;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.par;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.rap;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import com.xdev.jadoth.lang.reflection.JaReflect;
import com.xdev.jadoth.sqlengine.dbms.DbmsAdaptor;
import com.xdev.jadoth.sqlengine.exceptions.SQLEngineException;
import com.xdev.jadoth.sqlengine.exceptions.SQLEngineTableStructureChangedException;
import com.xdev.jadoth.sqlengine.interfaces.SqlExecutor;
import com.xdev.jadoth.sqlengine.internal.DatabaseGateway;
import com.xdev.jadoth.sqlengine.internal.SqlField;
import com.xdev.jadoth.sqlengine.internal.tables.SqlTrigger.Event;
/**
* The Class SqlDdlTable.
*
* @author Thomas Muenz
*/
public abstract class SqlDdlTable extends SqlTable
{
///////////////////////////////////////////////////////////////////////////
// constants //
/////////////////////
/**
*
*/
private static final long serialVersionUID = 3516721864501741331L;
///////////////////////////////////////////////////////////////////////////
// static fields //
/////////////////////
/** The Constant INSERT. */
protected static final Event INSERT = SqlTrigger.eINSERT;
/** The Constant DELETE. */
protected static final Event DELETE = SqlTrigger.eDELETE;
/** The Constant UPDATE. */
protected static final Event UPDATE = SqlTrigger.eUPDATE;
/** The Constant BEFORE. */
protected static final SqlTrigger.Time BEFORE = SqlTrigger.Time.BEFORE;
/** The Constant AFTER. */
protected static final SqlTrigger.Time AFTER = SqlTrigger.Time.BEFORE;
///////////////////////////////////////////////////////////////////////////
// static methods //
/////////////////////
/**
* UPDAT e_ of.
*
* @param columnNames the column names
* @return the event
*/
protected static final Event UPDATE_OF(final String[] columnNames){
return SqlTrigger.UPDATE_OF(columnNames);
}
/**
* Creates the trigger.
*
* @param time the time
* @param event the event
* @param action the action
* @return the sql trigger
*/
protected static SqlTrigger createTrigger(
final SqlTrigger.Time time,
final SqlTrigger.Event event,
final Object action
)
{
return new SqlTrigger(null, time, event, null, action);
}
////////////////////////
// Instance Variables //
////////////////////////
/** The db. */
public final Database db = new Database();
/** The ddl. */
public final Ddl ddl = new Ddl();
/** The util. */
public final Util util = new Util();
/** The initialize in db. */
private final boolean initializeInDB = true;
/** The initialized triggers. */
private boolean initializedTriggers = false;
//////////////////
// Constructors //
//////////////////
/**
* Instantiates a new sql ddl table.
*
* @param schema the schema
* @param name the name
* @param alias the alias
*/
public SqlDdlTable(final String schema, final String name, final String alias){
super(schema, name, alias);
}
///////////////////////
// Getters & Setters //
///////////////////////
////////////////////
// Public Methods //
////////////////////
/**
* @param newAlias
* @return
* @throws SQLEngineException
* @see com.xdev.jadoth.sqlengine.internal.tables.SqlTable#AS(java.lang.String)
*/
@Override
public synchronized SqlDdlTable AS(final String newAlias) throws SQLEngineException {
return (SqlDdlTable)super.AS(newAlias);
}
///////////////////////
// Protected Methods //
///////////////////////
/**
* Check index.
*
* @param definedIndex the defined index
* @param loadedIndices the loaded indices
* @return the int
*/
protected int checkIndex(final SqlIndex definedIndex, final SqlIndex[] loadedIndices) {
for (int i = 0; i < loadedIndices.length; i++) {
if(loadedIndices[i].equals(definedIndex)) {
return i;
}
}
return -1;
}
/**
* Check column.
*
* @param definedColumn the defined column
* @param loadedColumns the loaded columns
* @return the int
*/
protected int checkColumn(final SqlField definedColumn, final SqlField[] loadedColumns) {
for (int i = 0; i < loadedColumns.length; i++) {
if(loadedColumns[i].equals(definedColumn)) {
return i;
}
}
return -1;
}
/**
* Validate indices.
*
* @throws SQLEngineException the sQL engine exception
*/
protected void validateIndices() throws SQLEngineException {
final SqlIndex[] loadedIndices = this.getDatabaseGateway().getDbmsAdaptor().getRetrospectionAccessor().loadIndices(this);
final boolean[] found = new boolean[loadedIndices.length];
for (int i = 0; i < found.length; i++) {
found[i] = false;
}
final SqlDdlTable.Indices indices = this.util.getIndices();
if(indices != null) {
int loopFoundIndex = -1;
for (final Field f : JaReflect.getAllFields(indices.getClass())) {
final Object o = JaReflect.getFieldValue(f, indices);
if(o != null && o instanceof SqlIndex) {
final SqlIndex index = (SqlIndex)o;
loopFoundIndex = this.checkIndex(index, loadedIndices);
if(loopFoundIndex > -1) {
found[loopFoundIndex] = true;
// System.out.println("Found Index: "+loopSqlIndex.getCompareString());
}
else {
System.out.println("Missing Index: "+index.getCompareString());
if(this.getDatabaseGateway().indexValidation_createMissingIndices) {
if(!(index instanceof SqlPrimaryKey)) {
// System.out.println(" creating missing Index " + loopSqlIndex.getName());
this.getDatabaseGateway().getDbmsAdaptor().getDdlMapper().createIndex(index, false);
}
}
else {
throw new SQLEngineTableStructureChangedException("Missing Index: "+index.getCompareString());
}
}
}
}
}
for (int i = 0; i < loadedIndices.length; i++) {
if(!found[i]) {
// System.out.println("Undefined Index: "+loadedIndices[i].getCompareString());
if(this.getDatabaseGateway().indexValidation_dropUndefinedIndices) {
System.out.println(" dropping undefined Index " + loadedIndices[i].getName());
this.getDatabaseGateway().dropIndex(loadedIndices[i]);
}
else {
throw new SQLEngineTableStructureChangedException("Undefined Index: "+loadedIndices[i].getCompareString());
}
}
}
}
/**
* Initialize defined triggers.
*
* @param forceInitialize the force initialize
*/
protected void initializeDefinedTriggers(final boolean forceInitialize) {
if(this.initializedTriggers && !forceInitialize) {
return;
}
final SqlDdlTable.Triggers triggers = this.getTriggersIntern();
if(triggers != null) {
for (final Field f : JaReflect.getAllFields(triggers.getClass())) {
final Object o = JaReflect.getFieldValue(f, triggers);
if(o != null && o instanceof SqlTrigger) {
final SqlTrigger trigger = (SqlTrigger)o;
trigger.setName(f.getName());
trigger.setTable(this);
}
}
}
this.initializedTriggers = true;
}
/**
* Creates the column definition.
*
* @param column the column
* @return the string
*/
protected String createColumnDefinition(final SqlField column) {
if(column == null) {
return null;
}
final String name = column.getName();
if(name == null) {
return null;
}
final StringBuilder sb = new StringBuilder(20);
sb.append(name);
sb.append(_);
column.assembleType(sb, this.getDatabaseGateway().getDbmsAdaptor());
if(column.isNotNull()) {
sb.append(_);
sb.append(NOT_NULL);
}
if(column.isUnique()) {
sb.append(_);
sb.append(UNIQUE);
}
final Object defaultValue = column.getDefaultValue();
if(defaultValue != null) {
sb.append(_);
sb.append(DEFAULT);
sb.append(_);
sb.append(defaultValue.toString());
}
return sb.toString();
}
/**
* Validate columns.
*
* @throws SQLEngineException the sQL engine exception
*/
protected void validateColumns() throws SQLEngineException {
final SqlField[] loadedColumns = this.getDatabaseGateway().getDbmsAdaptor().getRetrospectionAccessor().loadColumns(this);
final boolean[] found = new boolean[loadedColumns.length];
for (int i = 0; i < found.length; i++) {
found[i] = false;
}
int loopFoundIndex = -1;
SqlField loopSqlColumn = null;
for (final Field f : JaReflect.getAllFields(this.getClass())) {
try {
loopSqlColumn = (SqlField)f.get(this);
}
catch (final ClassCastException e) {
// System.err.println(e);
continue;
}
catch (final NullPointerException e) {
// System.err.println(e);
continue;
}
catch (final IllegalAccessException e) {
// System.err.println(e);
continue;
}
if(loopSqlColumn == null) {
// System.err.println("null: "+f.getName());
continue;
}
loopFoundIndex = this.checkColumn(loopSqlColumn, loadedColumns);
if(loopFoundIndex > -1) {
found[loopFoundIndex] = true;
// System.out.println("Found Column: "+loopSqlColumn.getCompareString());
}
else {
// System.out.println("Missing Column: "+loopSqlColumn.getCompareString());
throw new SQLEngineTableStructureChangedException("Missing Column: "+loopSqlColumn.getCompareString());
}
}
for (int i = 0; i < loadedColumns.length; i++) {
if(!found[i]) {
// System.out.println("Undefined Column: "+loadedColumns[i].getCompareString());
throw new SQLEngineTableStructureChangedException("Undefined Column: "+loadedColumns[i].getCompareString());
}
}
}
/////////////////////
// Private Methods //
/////////////////////
//this is a little buggy in jave imho. Something like "parent" instead of "this" for inner classes is needed...
/**
* @return
* @see com.xdev.jadoth.sqlengine.internal.tables.SqlTable#getTopLevelInstance()
*/
@Override
protected SqlDdlTable getTopLevelInstance() {
return this;
}
/**
* Append column definitions.
*
* @param sb the sb
*/
private void appendColumnDefinitions(final StringBuilder sb)
{
final ArrayList fields = JaReflect.getAllFields(this.getClass(),Modifier.STATIC);
boolean notEmpty = false;
for (int i = 0, size = fields.size(); i < size; i++) {
final Object value = JaReflect.getFieldValue(fields.get(i), this);
if(! (value instanceof SqlField[])) continue;
for (final SqlField sf : (SqlField[])value) {
if(sf == null) continue;
if(notEmpty) {
sb.append(comma_).append(NEW_LINE);
}
else {
notEmpty = true;
}
sb.append(TAB).append(this.createColumnDefinition(sf));
}
}
}
///////////////////
// Inner Classes //
///////////////////
/**
* @return
* @see com.xdev.jadoth.sqlengine.internal.tables.SqlTable#getDbIntern()
*/
@Override
protected Database getDbIntern() {
return this.db;
}
/**
* Gets the ddl intern.
*
* @return the ddl intern
*/
protected Ddl getDdlIntern() {
return this.ddl;
}
/**
* Gets the triggers intern.
*
* @return the triggers intern
*/
protected Triggers getTriggersIntern() {
return null;
}
/**
* The Class Util.
*/
public class Util extends SqlTable.Util {
/**
* Gets the ddl.
*
* @return the ddl
*/
public Ddl getDdl() {
return SqlDdlTable.this.getDdlIntern();
}
// /**
// * @param reinitialize
// * @see net.jadoth.sqlengine.internal.tables.SqlTable.Util#initialize(boolean)
// */
// @Override
// public void initialize(final boolean reinitialize) {
// super.initialize(reinitialize);
// SqlDdlTable.this.getTopLevelInstance().initializeDefinedTriggers(reinitialize);
// }
/**
* Gets the triggers.
*
* @return the triggers
*/
public Triggers getTriggers() {
return SqlDdlTable.this.getTriggersIntern();
}
}
/**
* The Class Database.
*/
public class Database extends SqlTable.Database {
/**
* Instantiates a new database.
*/
protected Database() {
super();
}
/**
* Initialize for.
*
* @param databaseGateway the database gateway
* @return the sql ddl table
*/
public SqlDdlTable initializeFor(final DatabaseGateway> databaseGateway) {
this.setDatabaseGateway(databaseGateway);
this.initialize();
return SqlDdlTable.this.getTopLevelInstance();
}
/**
* Initialize.
*/
public void initialize() {
try {
SqlDdlTable.this.getDdlIntern().initialize(/*false*/);
} catch (final Exception e) {
//TODO RunTimeException weitergeben
}
}
/**
* Kill table.
*
* @throws SQLEngineException the sQL engine exception
*/
public void killTable() throws SQLEngineException
{
this.truncate();
this.getDatabaseGateway().execute(SqlExecutor.update, SqlDdlTable.this.ddl.DROP_TABLE());
}
}
/**
* The Class Triggers.
*/
public abstract class Triggers {
/**
* Instantiates a new triggers.
*/
protected Triggers() {
super();
}
/**
* Define triggers.
*
* @param the generic type
* @param dbms the dbms
*/
protected void defineTriggers(final DbmsAdaptor> dbms) {
//nothing in basic implementation, override only if needed
}
/**
* List triggers.
*
* @return the list
*/
public List listTriggers()
{
final ArrayList allFields = JaReflect.getAllFields(this.getClass());
final ArrayList definedTriggers = new ArrayList(allFields.size());
for (final Field f : allFields) {
final Object o = JaReflect.getFieldValue(f, this);
if(o != null && o instanceof SqlTrigger) {
definedTriggers.add((SqlTrigger)o);
}
}
return definedTriggers;
}
}
/**
* The Class Ddl.
*/
public class Ddl
{
/**
* Instantiates a new ddl.
*/
protected Ddl() {
super();
}
/**
* Initialize.
*
* @param forceInitialize the force initialize
* @return the sql ddl table
* @throws SQLEngineException the sQL engine exception
*/
public SqlDdlTable initialize(/*final boolean forceInitialize*/) throws SQLEngineException
{
SqlDdlTable.this.getTopLevelInstance().util.initialize(/*forceInitialize*/);
if(!SqlDdlTable.this.initializeInDB) {
return SqlDdlTable.this.getTopLevelInstance();
}
final DatabaseGateway> dbc = SqlDdlTable.this.getDatabaseGateway();
if(dbc == null || !dbc.isConnectionEnabled()) return SqlDdlTable.this.getTopLevelInstance();
final Triggers trg = SqlDdlTable.this.getTriggersIntern();
if(trg != null) {
trg.defineTriggers(dbc.getDbmsAdaptor());
}
if(SqlDdlTable.this.db.existsInDB()) {
if(SqlDdlTable.this.getDatabaseGateway().validateTableColumns) {
try {
SqlDdlTable.this.validateColumns();
} catch (final SQLEngineTableStructureChangedException e) {
// System.err.println(e);
}
}
if(SqlDdlTable.this.getDatabaseGateway().indexValidationEnabled) {
try {
SqlDdlTable.this.validateIndices();
} catch (final SQLEngineTableStructureChangedException e) {
// System.err.println(e);
}
}
}
else {
if(SqlDdlTable.this.columnNames != null && SqlDdlTable.this.columnNames.length > 0) {
this.createEverything();
}
else {
// System.err.println(this.toString() + " has no columns defined. No table created.");
}
}
return SqlDdlTable.this.getTopLevelInstance();
}
/**
* Gets the primary key.
*
* @return the primary key
*/
public SqlPrimaryKey getPrimaryKey() {
return SqlDdlTable.this.primaryKey;
}
/**
* Creates the everything.
*/
protected void createEverything(){
SqlDdlTable.this.getDdlIntern().preCreateActions();
SqlDdlTable.this.getDdlIntern().createTable();
SqlDdlTable.this.getDdlIntern().createIndices();
SqlDdlTable.this.getDdlIntern().createTriggers();
SqlDdlTable.this.getDdlIntern().postCreateActions();
}
/**
* Pre create actions.
*
* @return the object
*/
protected Object preCreateActions() {
return SqlDdlTable.this.getDatabaseGateway().getDbmsAdaptor().getDdlMapper().preCreateTableActions(SqlDdlTable.this.getTopLevelInstance());
}
/**
* Creates the table.
*
* @throws SQLEngineException the sQL engine exception
*/
public void createTable() throws SQLEngineException {
SqlDdlTable.this.getDatabaseGateway().getDbmsAdaptor().getDdlMapper().createTable(SqlDdlTable.this.getTopLevelInstance());
}
/**
* Post create actions.
*
* @return the object
*/
protected Object postCreateActions() {
return SqlDdlTable.this.getDatabaseGateway().getDbmsAdaptor().getDdlMapper().postCreateTableActions(SqlDdlTable.this.getTopLevelInstance());
}
/**
* Recreate table.
*
* @throws SQLEngineException the sQL engine exception
*/
public void recreateTable() throws SQLEngineException {
SqlDdlTable.this.db.killTable();
this.createEverything();
}
/**
* Creates the indices.
*
* @throws SQLEngineException the sQL engine exception
*/
public void createIndices() throws SQLEngineException {
SqlDdlTable.this.getDatabaseGateway().getDbmsAdaptor().getDdlMapper().createIndices(SqlDdlTable.this.getTopLevelInstance());
}
/**
* Creates the triggers.
*
* @throws SQLEngineException the sQL engine exception
*/
public void createTriggers() throws SQLEngineException {
SqlDdlTable.this.getDatabaseGateway().getDbmsAdaptor().getDdlMapper().createTriggers(SqlDdlTable.this.getTopLevelInstance());
}
/**
* DRO p_ table.
*
* @return the string
*/
public String DROP_TABLE() {
return DROP_TABLE+_+SqlDdlTable.this.getTopLevelInstance().toString();
}
/**
* CREAT e_ table.
*
* @return the string
*/
public String CREATE_TABLE()
{
final StringBuilder sb = new StringBuilder(1024)
.append(CREATE_TABLE).append(_).append(SqlDdlTable.this.getTopLevelInstance().toString())
.append(_).append(par).append(NEW_LINE);
SqlDdlTable.this.appendColumnDefinitions(sb);
if(SqlDdlTable.this.primaryKey != null) {
sb.append(comma_).append(NEW_LINE)
.append(NEW_LINE)
.append(TAB)
.append(SqlDdlTable.this.primaryKey.CREATE_INDEX());
}
sb.append(NEW_LINE);
sb.append(rap);
return sb.toString();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy