/*
* Copyright (c) 2008, 2009, 2011-2013, 2015 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.net4j.internal.db.ddl;
import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBType;
import org.eclipse.net4j.db.ddl.IDBField;
import org.eclipse.net4j.db.ddl.IDBIndex;
import org.eclipse.net4j.db.ddl.IDBSchema;
import org.eclipse.net4j.db.ddl.IDBSchemaElement;
import org.eclipse.net4j.db.ddl.IDBSchemaVisitor;
import org.eclipse.net4j.db.ddl.IDBTable;
import org.eclipse.net4j.db.ddl.SchemaElementNotFoundException;
import org.eclipse.net4j.spi.db.ddl.InternalDBField;
import org.eclipse.net4j.spi.db.ddl.InternalDBSchema;
import org.eclipse.net4j.spi.db.ddl.InternalDBTable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @author Eike Stepper
*/
public class DBTable extends DBSchemaElement implements InternalDBTable
{
private static final long serialVersionUID = 1L;
private IDBSchema schema;
private List<IDBField> fields = new ArrayList<IDBField>();
private List<IDBIndex> indices = new ArrayList<IDBIndex>();
public DBTable(IDBSchema schema, String name)
{
super(name);
this.schema = schema;
}
/**
* Constructor for deserialization.
*/
protected DBTable()
{
}
@Override
public IDBTable getWrapper()
{
return (IDBTable)super.getWrapper();
}
public SchemaElementType getSchemaElementType()
{
return SchemaElementType.TABLE;
}
public IDBSchema getSchema()
{
return schema;
}
public IDBSchema getParent()
{
return getSchema();
}
public IDBField addField(String name, DBType type)
{
return addField(name, type, IDBField.DEFAULT, IDBField.DEFAULT, false);
}
public IDBField addField(String name, DBType type, boolean notNull)
{
return addField(name, type, IDBField.DEFAULT, IDBField.DEFAULT, notNull);
}
public IDBField addField(String name, DBType type, int precision)
{
return addField(name, type, precision, IDBField.DEFAULT, false);
}
public IDBField addField(String name, DBType type, int precision, boolean notNull)
{
return addField(name, type, precision, IDBField.DEFAULT, notNull);
}
public IDBField addField(String name, DBType type, int precision, int scale)
{
return addField(name, type, precision, scale, false);
}
public IDBField addField(String name, DBType type, int precision, int scale, boolean notNull)
{
assertUnlocked();
if (getField(name) != null)
{
throw new DBException("Field exists: " + name); //$NON-NLS-1$
}
int position = fields.size();
IDBField field = new DBField(this, name, type, precision, scale, notNull, position);
fields.add(field);
resetElements();
return field;
}
public void removeField(IDBField fieldToRemove)
{
assertUnlocked();
boolean found = false;
for (Iterator<IDBField> it = fields.iterator(); it.hasNext();)
{
IDBField field = it.next();
if (found)
{
((InternalDBField)field).setPosition(field.getPosition() - 1);
}
else if (field == fieldToRemove)
{
it.remove();
found = true;
}
}
resetElements();
}
public IDBField getFieldSafe(String name) throws SchemaElementNotFoundException
{
IDBField field = getField(name);
if (field == null)
{
throw new SchemaElementNotFoundException(this, SchemaElementType.FIELD, name);
}
return field;
}
public IDBField getField(String name)
{
return findElement(getFields(), name);
}
public IDBField getField(int position)
{
return fields.get(position);
}
public int getFieldCount()
{
return fields.size();
}
public IDBField[] getFields()
{
return fields.toArray(new IDBField[fields.size()]);
}
public IDBField[] getFields(String... fieldNames) throws SchemaElementNotFoundException
{
List<IDBField> result = new ArrayList<IDBField>();
for (String fieldName : fieldNames)
{
IDBField field = getFieldSafe(fieldName);
result.add(field);
}
return result.toArray(new IDBField[result.size()]);
}
public boolean hasIndexFor(IDBField... fields)
{
for (IDBIndex index : indices)
{
IDBField[] indexFields = index.getFields();
if (startsWith(indexFields, fields))
{
return true;
}
}
return false;
}
public IDBIndex addIndex(String name, IDBIndex.Type type, IDBField... fields)
{
assertUnlocked();
if (name == null)
{
int position = indices.size();
name = ((InternalDBSchema)schema).createIndexName(this, type, fields, position);
}
if (getIndex(name) != null)
{
throw new DBException("Index exists: " + name); //$NON-NLS-1$
}
if (type == IDBIndex.Type.PRIMARY_KEY)
{
for (IDBIndex index : getIndices())
{
if (index.getType() == IDBIndex.Type.PRIMARY_KEY)
{
throw new DBException("Primary key exists: " + index); //$NON-NLS-1$
}
}
}
IDBIndex index = new DBIndex(this, name, type, fields);
indices.add(index);
resetElements();
return index;
}
public IDBIndex addIndex(String name, IDBIndex.Type type, String... fieldNames)
{
return addIndex(name, type, getFields(fieldNames));
}
public IDBIndex addIndexEmpty(String name, IDBIndex.Type type)
{
return addIndex(name, type, NO_FIELDS);
}
public IDBIndex addIndex(IDBIndex.Type type, IDBField... fields)
{
return addIndex(null, type, fields);
}
public IDBIndex addIndex(IDBIndex.Type type, String... fieldNames)
{
IDBField[] fields = getFields(fieldNames);
return addIndex(type, fields);
}
public IDBIndex addIndexEmpty(IDBIndex.Type type)
{
return addIndex(type, NO_FIELDS);
}
public void removeIndex(IDBIndex indexToRemove)
{
assertUnlocked();
if (indices.remove(indexToRemove))
{
resetElements();
}
}
public IDBIndex getIndexSafe(String name) throws SchemaElementNotFoundException
{
IDBIndex index = getIndex(name);
if (index == null)
{
throw new SchemaElementNotFoundException(this, SchemaElementType.INDEX, name);
}
return index;
}
public IDBIndex getIndex(String name)
{
return findElement(getIndices(), name);
}
public IDBIndex getIndex(int position)
{
return indices.get(position);
}
public int getIndexCount()
{
return indices.size();
}
public IDBIndex[] getIndices()
{
return indices.toArray(new IDBIndex[indices.size()]);
}
public IDBIndex getPrimaryKeyIndex()
{
for (IDBIndex index : indices)
{
if (index.getType() == IDBIndex.Type.PRIMARY_KEY)
{
return index;
}
}
return null;
}
public String getFullName()
{
return getName();
}
public void remove()
{
schema.removeTable(getName());
}
public String sqlInsert()
{
StringBuilder builder = new StringBuilder();
builder.append("INSERT INTO "); //$NON-NLS-1$
builder.append(getName());
builder.append(" VALUES ("); //$NON-NLS-1$
for (int i = 0; i < fields.size(); i++)
{
if (i > 0)
{
builder.append(", "); //$NON-NLS-1$
}
builder.append("?"); //$NON-NLS-1$
}
builder.append(")"); //$NON-NLS-1$
return builder.toString();
}
@Override
protected void collectElements(List<IDBSchemaElement> elements)
{
elements.addAll(fields);
elements.addAll(indices);
}
@Override
protected void doAccept(IDBSchemaVisitor visitor)
{
visitor.visit(this);
}
private void assertUnlocked()
{
((InternalDBSchema)schema).assertUnlocked();
}
private static boolean startsWith(IDBField[] indexFields, IDBField[] fields)
{
int length = fields.length;
if (length <= indexFields.length)
{
for (int i = 0; i < length; i++)
{
IDBField field = fields[i];
if (field != indexFields[i])
{
return false;
}
}
return true;
}
return false;
}
}