/*******************************************************************************
* Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com)
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v3
* which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt
******************************************************************************/
package com.opendoorlogistics.core.tables.memory;
import gnu.trove.map.hash.TIntObjectHashMap;
import java.util.ArrayList;
import com.opendoorlogistics.api.tables.ODLDatastore;
import com.opendoorlogistics.api.tables.ODLDatastoreAlterable;
import com.opendoorlogistics.api.tables.ODLListener;
import com.opendoorlogistics.api.tables.ODLTableAlterable;
import com.opendoorlogistics.api.tables.ODLTableDefinition;
import com.opendoorlogistics.api.tables.ODLTableDefinitionAlterable;
import com.opendoorlogistics.api.tables.TableFlags;
import com.opendoorlogistics.core.tables.*;
import com.opendoorlogistics.core.tables.utils.TableUtils;
import com.opendoorlogistics.core.utils.DeepCopyable;
import com.opendoorlogistics.core.utils.IntIDGenerator;
import com.opendoorlogistics.core.utils.IntIDGenerator.IsExistingId;
final public class ODLDatastoreImpl <T extends ODLTableDefinition> implements ODLDatastoreAlterable<T>, DeepCopyable<ODLDatastoreImpl<T>>{
/**
*
*/
private static final long serialVersionUID = 4261272361071414989L;
private final ArrayList<T> tablesByIndx = new ArrayList<>();
private final TIntObjectHashMap<T> tablesById = new TIntObjectHashMap<>();
private final ODLTableFactory<T> factory;
private long flags;
protected final IntIDGenerator tableIdGenerator = new IntIDGenerator(new IsExistingId() {
@Override
public boolean isExistingId(int id) {
return tablesById.containsKey(id);
}
});
public ODLDatastoreImpl(ODLTableFactory<T> factory) {
this.factory = factory;
this.flags |= TableFlags.UI_EDIT_PERMISSION_FLAGS;
}
@SuppressWarnings("unchecked")
protected ODLDatastoreImpl(ODLDatastoreImpl<T> copyThis){
this.factory = copyThis.factory;
this.flags = copyThis.flags;
for(T table : copyThis.tablesByIndx){
if(ODLTableImpl.class.isInstance(table)==false){
throw new UnsupportedOperationException();
}
addTable((T)table.deepCopyWithShallowValueCopy());
}
this.tableIdGenerator.setNextId(copyThis.tableIdGenerator.getNextId());
}
@Override
public long getFlags() {
return flags;
}
@Override
public void setFlags(long flags) {
this.flags = flags;
}
@Override
public int getTableCount() {
return tablesByIndx.size();
}
@Override
public T getTableAt(int i) {
return tablesByIndx.get(i);
}
/**
* Add the table returning its index or -1 if rejected
* @param table
* @param logger
* @return
*/
public int addTable(T table){
if(TableUtils.findTableIndex(this, table.getName(), true)!=-1){
throw new RuntimeException("Table already exists: " + table.getName());
}
if(table.getImmutableId()==-1){
throw new RuntimeException("Invalid table immutable id in table: " + table.getName());
}
// we throw an exception if the id is already used because this will
// be caused by a code error rather than a user error
if(tablesById.get(table.getImmutableId())!=null){
throw new RuntimeException("Duplicate table id");
}
tablesByIndx.add(table);
tablesById.put(table.getImmutableId(), table);
return tablesByIndx.size()-1;
}
@SuppressWarnings("unchecked")
public boolean addTables(ODLDatastore<? extends ODLTableDefinition> database){
for(int i =0 ; i < database.getTableCount() ; i++){
if(addTable((T)database.getTableAt(i))==-1){
return false;
}
}
return true;
}
@Override
public T createTable(String tablename, int id) {
// assign id
if(id==-1){
id = tableIdGenerator.generateId();
}
T table = factory.create(this,tablename, id);
// give table default permissions
grantDefaultTablePermissions(this,table);
if( addTable(table)!=-1){
return table;
}
return null;
}
public static void grantDefaultTablePermissions(ODLDatastore<? extends ODLTableDefinition> ds,ODLTableDefinition table) {
if(ODLTableDefinitionAlterable.class.isInstance(table)){
ODLTableDefinitionAlterable dfn= (ODLTableDefinitionAlterable)table;
// remove default permission flags
long flags = dfn.getFlags() & (~TableFlags.UI_EDIT_PERMISSION_FLAGS);
// re-add the datastore ones
flags |= (TableFlags.UI_EDIT_PERMISSION_FLAGS & ds.getFlags());
dfn.setFlags(flags);
}
}
@Override
public String toString(){
return TableUtils.convertToString(this);
}
@Override
public void addListener(ODLListener tml, int ...tableIds) {
//throwListenersUnsupportedException();
}
@Override
public void removeListener( ODLListener tml) {
// throwListenersUnsupportedException();
}
@Override
public T getTableByImmutableId(int id) {
return tablesById.get(id);
}
public static final ODLDatastoreAlterableFactory<ODLTableAlterable> alterableFactory = new ODLDatastoreAlterableFactory<ODLTableAlterable>() {
@Override
public ODLDatastoreAlterable<ODLTableAlterable> create() {
return new ODLDatastoreImpl<>(ODLTableImpl.ODLTableAlterableFactory);
}
};
@Override
public void disableListeners() {
//throwListenersUnsupportedException();
}
@Override
public void enableListeners() {
//throwListenersUnsupportedException();
}
@Override
public void deleteTableById(int tableId) {
T table = tablesById.get(tableId);
if(table!=null){
tablesByIndx.remove(table);
tablesById.remove(tableId);
}
}
@Override
public void startTransaction() {
// TODO Auto-generated method stub
}
@Override
public void endTransaction() {
// TODO Auto-generated method stub
}
@Override
public boolean isInTransaction() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean setTableName(int tableId, String newName) {
ODLTableDefinition dfn = TableUtils.findTable(this, newName, true);
if(dfn!=null && dfn.getImmutableId()!=tableId){
return false;
}
ODLTableDefinitionImpl table =(ODLTableDefinitionImpl) tablesById.get(tableId);
if(table!=null){
table.setName(newName);
}
return true;
}
@Override
public ODLDatastoreImpl<T> deepCopy() {
return new ODLDatastoreImpl<>(this);
}
@Override
public ODLDatastoreAlterable<T> deepCopyWithShallowValueCopy(boolean lazyCopy) {
return deepCopy();
}
@Override
public void rollbackTransaction() {
// TODO Auto-generated method stub
}
@Override
public boolean isRollbackSupported() {
// TODO Auto-generated method stub
return false;
}
}