/*
* Copyright (c) 2013, 2015, 2016 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.delta;
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.IDBIndexField;
import org.eclipse.net4j.db.ddl.IDBSchema;
import org.eclipse.net4j.db.ddl.IDBTable;
import org.eclipse.net4j.db.ddl.delta.IDBDelta;
import org.eclipse.net4j.db.ddl.delta.IDBDeltaVisitor;
import org.eclipse.net4j.db.ddl.delta.IDBFieldDelta;
import org.eclipse.net4j.db.ddl.delta.IDBIndexDelta;
import org.eclipse.net4j.db.ddl.delta.IDBIndexFieldDelta;
import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta;
import org.eclipse.net4j.db.ddl.delta.IDBTableDelta;
import org.eclipse.net4j.spi.db.ddl.InternalDBIndex;
import org.eclipse.net4j.spi.db.ddl.InternalDBSchema;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Eike Stepper
*/
public final class DBSchemaDelta extends DBDelta implements IDBSchemaDelta
{
private static final long serialVersionUID = 1L;
private Map<String, IDBTableDelta> tableDeltas = new HashMap<String, IDBTableDelta>();
public DBSchemaDelta(String name, ChangeKind changeKind)
{
super(null, name, changeKind);
}
public DBSchemaDelta(IDBSchema schema, IDBSchema oldSchema)
{
this(schema.getName(), oldSchema == null ? ChangeKind.ADD : ChangeKind.CHANGE);
IDBTable[] tables = schema.getTables();
IDBTable[] oldTables = oldSchema == null ? InternalDBSchema.NO_TABLES : oldSchema.getTables();
compare(tables, oldTables, new SchemaElementComparator<IDBTable>()
{
public void compare(IDBTable table, IDBTable oldTable)
{
DBTableDelta tableDelta = new DBTableDelta(DBSchemaDelta.this, table, oldTable);
if (!tableDelta.isEmpty())
{
addTableDelta(tableDelta);
}
}
});
}
/**
* Constructor for deserialization.
*/
protected DBSchemaDelta()
{
}
public DeltaType getDeltaType()
{
return DeltaType.SCHEMA;
}
public int getTableDeltaCount()
{
return tableDeltas.size();
}
public DBTableDelta getTableDelta(String name)
{
return (DBTableDelta)tableDeltas.get(name);
}
public Map<String, IDBTableDelta> getTableDeltas()
{
return Collections.unmodifiableMap(tableDeltas);
}
public IDBTableDelta[] getTableDeltasSortedByName()
{
IDBTableDelta[] result = tableDeltas.values().toArray(new IDBTableDelta[tableDeltas.size()]);
Arrays.sort(result);
return result;
}
public void addTableDelta(IDBTableDelta tableDelta)
{
tableDeltas.put(tableDelta.getName(), tableDelta);
resetElements();
}
public IDBSchema getSchemaElement(IDBSchema schema)
{
return schema;
}
public void applyTo(IDBSchema schema)
{
IDBDeltaVisitor visitor = new DBSchemaDelta.Applier(schema);
accept(visitor);
}
@Override
public String toString()
{
return MessageFormat.format("DBSchemaDelta[name={0}, kind={1}, tableDeltas={2}]", getName(), getChangeKind(), tableDeltas.values());
}
@Override
protected void doAccept(IDBDeltaVisitor visitor)
{
visitor.visit(this);
}
@Override
protected void collectElements(List<IDBDelta> elements)
{
elements.addAll(tableDeltas.values());
}
/**
* @author Eike Stepper
*/
public static class Applier extends IDBDeltaVisitor.Default
{
private final IDBSchema schema;
public Applier(IDBSchema schema)
{
this.schema = schema;
}
public final IDBSchema getSchema()
{
return schema;
}
@Override
public void added(IDBTableDelta delta)
{
String name = delta.getName();
schema.addTable(name);
}
@Override
public void removed(IDBTableDelta delta)
{
IDBTable table = delta.getSchemaElement(schema);
table.remove();
}
@Override
public void changed(IDBTableDelta delta)
{
}
@Override
public void added(IDBFieldDelta delta)
{
String name = delta.getName();
DBType type = delta.getPropertyValue(IDBFieldDelta.TYPE_PROPERTY);
int precision = delta.getPropertyValue(IDBFieldDelta.PRECISION_PROPERTY);
int scale = delta.getPropertyValue(IDBFieldDelta.SCALE_PROPERTY);
boolean notNull = delta.getPropertyValue(IDBFieldDelta.NOT_NULL_PROPERTY);
IDBTable table = delta.getParent().getSchemaElement(schema);
table.addField(name, type, precision, scale, notNull);
}
@Override
public void removed(IDBFieldDelta delta)
{
IDBField field = delta.getSchemaElement(schema);
field.remove();
}
@Override
public void changed(IDBFieldDelta delta)
{
}
@Override
public void added(IDBIndexDelta delta)
{
String name = delta.getName();
IDBIndex.Type type = delta.getPropertyValue(IDBIndexDelta.TYPE_PROPERTY);
Boolean optional = delta.getPropertyValue(IDBIndexDelta.OPTIONAL_PROPERTY);
IDBTable table = delta.getParent().getSchemaElement(schema);
InternalDBIndex index = (InternalDBIndex)table.addIndexEmpty(name, type);
index.setOptional(optional == Boolean.TRUE);
}
@Override
public void removed(IDBIndexDelta delta)
{
IDBIndex index = delta.getSchemaElement(schema);
index.remove();
}
@Override
public void changed(IDBIndexDelta delta)
{
}
@Override
public void added(IDBIndexFieldDelta delta)
{
IDBIndexDelta parent = delta.getParent();
IDBTable table = parent.getParent().getSchemaElement(schema);
String name = delta.getName();
IDBField field = table.getField(name);
IDBIndex index = parent.getSchemaElement(schema);
index.addIndexField(field);
}
@Override
public void removed(IDBIndexFieldDelta delta)
{
IDBIndexField indexField = delta.getSchemaElement(schema);
indexField.remove();
}
@Override
public void changed(IDBIndexFieldDelta delta)
{
}
}
}