/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.persistence;
import java.rmi.RemoteException;
import java.util.Iterator;
import java.util.Map;
import com.servoy.base.util.DataSourceUtilsBase;
import com.servoy.j2db.J2DBGlobals;
import com.servoy.j2db.Messages;
import com.servoy.j2db.documentation.ServoyDocumented;
import com.servoy.j2db.util.DataSourceUtils;
import com.servoy.j2db.util.UUID;
/**
* This class is a repository node for storing scriptcalculations under, because jaleman said that there easily are 300-1000 calcs in a solution
*
* @author jblok
*/
@ServoyDocumented(category = ServoyDocumented.DESIGNTIME, publicName = "Table", typeCode = IRepository.TABLENODES)
public class TableNode extends AbstractBase implements ISupportChilds
{
private static final long serialVersionUID = 1L;
/*
* _____________________________________________________________ Declaration and definition of constructors
*/
TableNode(ISupportChilds parent, int element_id, UUID uuid)
{
super(IRepository.TABLENODES, parent, element_id, uuid);
}
/*
* _____________________________________________________________ Methods for ScriptCalculation handling
*/
public Iterator<ScriptCalculation> getScriptCalculations()
{
return getObjects(IRepository.SCRIPTCALCULATIONS);
}
public ScriptCalculation createNewScriptCalculation(IValidateName validator, String calcName, String userTemplate) throws RepositoryException
{
String name = calcName == null ? "untitled" : calcName; //$NON-NLS-1$
//check if name is in use
ValidatorSearchContext ft = new ValidatorSearchContext(getTable(), IRepository.SCRIPTCALCULATIONS);
validator.checkName(name, 0, ft, false);
ScriptCalculation obj = (ScriptCalculation)getRootObject().getChangeHandler().createNewObject(this, IRepository.SCRIPTCALCULATIONS);
//set all the required properties
obj.setName(name);
MethodTemplate template = MethodTemplate.getTemplate(ScriptCalculation.class, null);
obj.setDeclaration(template.getMethodDeclaration(name, "\treturn 1;", userTemplate)); //$NON-NLS-1$
addChild(obj);
return obj;
}
public ScriptMethod createNewFoundsetMethod(IValidateName validator, String methodName, String userTemplate) throws RepositoryException
{
String name = methodName == null ? "untitled" : methodName; //$NON-NLS-1$
//check if name is in use
ValidatorSearchContext ft = new ValidatorSearchContext(this, IRepository.METHODS);
validator.checkName(name, 0, ft, false);
ScriptMethod obj = (ScriptMethod)getRootObject().getChangeHandler().createNewObject(this, IRepository.METHODS);
//set all the required properties
obj.setName(name);
MethodTemplate template = MethodTemplate.getTemplate(ScriptMethod.class, null);
obj.setDeclaration(template.getMethodDeclaration(name, null, userTemplate));
addChild(obj);
return obj;
}
/*
* _____________________________________________________________ Methods for AggregateVariable handling
*/
public Iterator<AggregateVariable> getAggregateVariables()
{
return getObjects(IRepository.AGGREGATEVARIABLES);
}
AggregateVariable createNewAggregateVariable(IValidateName validator, String calcName, int atype, String dataProviderIDToAggregate)
throws RepositoryException
{
String name = calcName == null ? "untitled" : calcName; //$NON-NLS-1$
//check if name is in use
ValidatorSearchContext ft = new ValidatorSearchContext(getTable(), IRepository.AGGREGATEVARIABLES);
validator.checkName(name, 0, ft, true);
AggregateVariable obj = (AggregateVariable)getRootObject().getChangeHandler().createNewObject(this, IRepository.AGGREGATEVARIABLES);
//set all the required properties
obj.setName(name);
obj.setType(atype);
obj.setDataProviderIDToAggregate(dataProviderIDToAggregate);
addChild(obj);
return obj;
}
public Iterator<ScriptMethod> getFoundsetMethods(boolean sort)
{
return Solution.getScriptMethods(getAllObjectsAsList(), null, sort);
}
public ScriptMethod getFoundsetMethod(int methodId)
{
return AbstractBase.selectById(getFoundsetMethods(false), methodId);
}
/*
* _____________________________________________________________ The methods below belong to this class
*/
public void setDataSource(String arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_DATASOURCE, arg);
table = null;
}
/**
* The datasource of this table.
*/
public String getDataSource()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_DATASOURCE);
}
public void setTableName(String name)
{
setDataSource(DataSourceUtils.createDBTableDataSource(getServerName(), name));
}
public String getTableName()
{
String[] stn = DataSourceUtilsBase.getDBServernameTablename(getDataSource());
return stn == null ? null : stn[1];
}
public void setServerName(String arg)
{
setDataSource(DataSourceUtils.createDBTableDataSource(arg, getTableName()));
}
public String getServerName()
{
String[] stn = DataSourceUtilsBase.getDBServernameTablename(getDataSource());
return stn == null ? null : stn[0];
}
private transient Table table = null;
public Table getTable() throws RepositoryException
{
if (table == null)
{
String dataSource = getDataSource();
if (dataSource == null)
{
return null;
}
String[] stn = DataSourceUtilsBase.getDBServernameTablename(dataSource);
if (stn != null)
{
try
{
IServer server = getRootObject().getServer(stn[0]);
if (server == null)
{
throw new RepositoryException(Messages.getString("servoy.exception.serverNotFound", new Object[] { stn[0] })); //$NON-NLS-1$
}
table = (Table)server.getTable(stn[1]);
}
catch (RemoteException e)
{
throw new RepositoryException(e);
}
}
else
{
// not a server/table combi, ask the current clients foundset manager
if (J2DBGlobals.getServiceProvider() != null)
{
table = (Table)J2DBGlobals.getServiceProvider().getFoundSetManager().getTable(dataSource);
}
}
}
return table;
}
public void clearTable()
{
table = null;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("TableNode{"); //$NON-NLS-1$
sb.append(getDataSource());
sb.append("}\n"); //$NON-NLS-1$
for (IPersist obj : getAllObjectsAsList())
{
sb.append(obj);
sb.append('\n');
}
return sb.toString();
}
/**
* A method that is executed before an insert operation. The method can block the insert operation by returning false.
*
* @templatedescription
* Record pre-insert trigger
* Validate the record to be inserted.
* When false is returned the record will not be inserted in the database.
* When an exception is thrown the record will also not be inserted in the database but it will be added to databaseManager.getFailedRecords(),
* the thrown exception can be retrieved via record.exception.getValue().
* @templatename onRecordInsert
* @templatetype Boolean
* @templateparam JSRecord<${dataSource}> record record that will be inserted
* @templateaddtodo
* @templatecode
*
* var not_valid = false;
* // test if it is valid.
*
* // throw exception to pass info to handler, will be returned in record.exception.getValue() when record.exception is a DataException
* if (not_valid) throw 'cannot insert'
*
* // return boolean to indicate success
* return true
*/
public int getOnInsertMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONINSERTMETHODID).intValue();
}
public void setOnInsertMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONINSERTMETHODID, arg);
}
/**
* A method that is executed before an update operation. A method can block the update by returning false.
*
* @templatedescription
* Record pre-update trigger
* Validate the record to be updated.
* When false is returned the record will not be updated in the database.
* When an exception is thrown the record will also not be updated in the database but it will be added to databaseManager.getFailedRecords(),
* the thrown exception can be retrieved via record.exception.getValue().
* @templatename onRecordUpdate
* @templatetype Boolean
* @templateparam JSRecord<${dataSource}> record record that will be updated
* @templateaddtodo
* @templatecode
*
* var not_valid = false;
* // test if it is valid.
*
* // throw exception to pass info to handler, will be returned in record.exception.getValue() when record.exception is a DataException
* if (not_valid) throw 'cannot update'
*
* // return boolean to indicate success
* return true
*/
public int getOnUpdateMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONUPDATEMETHODID).intValue();
}
public void setOnUpdateMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONUPDATEMETHODID, arg);
}
/**
* A method that is executed before a delete operation. The method can block the delete operation by returning false.
*
* @templatedescription
* Record pre-delete trigger
* Validate the record to be deleted.
* When false is returned the record will not be deleted in the database.
* When an exception is thrown the record will also not be deleted in the database but it will be added to databaseManager.getFailedRecords(),
* the thrown exception can be retrieved via record.exception.getValue().
* @templatename onRecordDelete
* @templatetype Boolean
* @templateparam JSRecord<${dataSource}> record record that will be deleted
* @templateaddtodo
* @templatecode
*
* var not_valid = false;
* // test if it is valid.
*
* // throw exception to pass info to handler, will be returned in record.exception.getValue() when record.exception is a DataException
* if (not_valid) throw 'cannot delete'
*
* // return boolean to indicate success
* return true
*/
public int getOnDeleteMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONDELETEMETHODID).intValue();
}
public void setOnDeleteMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONDELETEMETHODID, arg);
}
/**
* A method that is executed after an insert operation.
*
* @templatedescription Record after-insert trigger
* @templatename afterRecordInsert
* @templateparam JSRecord<${dataSource}> record record that is inserted
* @templateaddtodo
*/
public int getOnAfterInsertMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERINSERTMETHODID).intValue();
}
public void setOnAfterInsertMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERINSERTMETHODID, arg);
}
/**
* A method that is executed after an update operation.
*
* @templatedescription Record after-update trigger
* @templatename afterRecordUpdate
* @templateparam JSRecord<${dataSource}> record record that is updated
* @templateaddtodo
*/
public int getOnAfterUpdateMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERUPDATEMETHODID).intValue();
}
public void setOnAfterUpdateMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERUPDATEMETHODID, arg);
}
/**
* A method that is executed after a delete operation.
*
* @templatedescription Record after-delete trigger
* @templatename afterRecordDelete
* @templateparam JSRecord<${dataSource}> record record that is deleted
* @templateaddtodo
*/
public int getOnAfterDeleteMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERDELETEMETHODID).intValue();
}
public void setOnAfterDeleteMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERDELETEMETHODID, arg);
}
/**
* A method that is executed before a record is created. The method can block the creation by returning false.
*
* @templatedescription
* Record pre-create trigger
* When false is returned the record will not be created in the foundset.
* @templatename onFoundSetRecordCreate
* @templatetype Boolean
* @templateaddtodo
* @templatecode
*
* // return true so that the record can be created
* return true
*/
public int getOnCreateMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONCREATEMETHODID).intValue();
}
public void setOnCreateMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONCREATEMETHODID, arg);
}
/**
* A method that is executed before a foundset is going into find mode. The method can block the mode change.
*
* @templatedescription
* Foundset pre-find trigger
* When false is returned the foundset will not go into find mode.
* @templatename onFoundSetFind
* @templatetype Boolean
* @templateaddtodo
* @templatecode
*
* // return true so that it will go into find mode.
* return true
*/
public int getOnFindMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONFINDMETHODID).intValue();
}
public void setOnFindMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONFINDMETHODID, arg);
}
/**
* A method that is executed after a foundset has switched to find mode.
*
* @templatedescription
* Foundset post-find trigger
* @templatename afterFoundSetFind
* @templateaddtodo
* @templatecode
*/
public int getOnAfterFindMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERFINDMETHODID).intValue();
}
public void setOnAfterFindMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERFINDMETHODID, arg);
}
/**
* A method that is executed before search() is called on a foundset in find mode. The method can block the search (foundset will stay in find mode).
*
* @templatedescription
* Foundset pre-search trigger
* When false is returned the search will not be executed and the foundset will stay in find mode.
* @templatename onFoundSetSearch
* @templateparam Boolean clearLastResults
* @templateparam Boolean reduceSearch
* @templatetype Boolean
* @templateaddtodo
* @templatecode
*
* // return true so that the search will go on.
* return true
*/
public int getOnSearchMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONSEARCHMETHODID).intValue();
}
public void setOnSearchMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONSEARCHMETHODID, arg);
}
/**
* A method that is executed after a search is executed for a foundset.
* @templatedescription
* Foundset post-search trigger
* @templatename afterFoundSetSearch
* @templateaddtodo
* @templatecode
*/
public int getOnAfterSearchMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERSEARCHMETHODID).intValue();
}
public void setOnAfterSearchMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERSEARCHMETHODID, arg);
}
/**
* A method that is executed after a new record is created.
*
* @templatedescription Record after-create trigger
* @templatename afterFoundSetRecordCreate
* @templateparam JSRecord<${dataSource}> record record that is created
* @templateaddtodo
*/
public int getOnAfterCreateMethodID()
{
return getTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERCREATEMETHODID).intValue();
}
public void setOnAfterCreateMethodID(int arg)
{
setTypedProperty(StaticContentSpecLoader.PROPERTY_ONAFTERCREATEMETHODID, arg);
}
public boolean isEmpty()
{
// Table node is empty if it has no method/var and no property set (except for dataSource)
if (getAllObjects().hasNext())
{
return false;
}
Map<String, Object> props = getPropertiesMap();
return props.isEmpty() || (props.size() == 1 && props.containsKey(StaticContentSpecLoader.PROPERTY_DATASOURCE.getPropertyName()));
}
public ScriptCalculation getScriptCalculation(String name)
{
if (name == null) return null;
return AbstractBase.selectByName(new TypeIterator<ScriptCalculation>(getAllObjects(), IRepository.SCRIPTCALCULATIONS), name);
}
public AggregateVariable getAggregateVariable(String name)
{
if (name == null) return null;
return AbstractBase.selectByName(new TypeIterator<AggregateVariable>(getAllObjects(), IRepository.AGGREGATEVARIABLES), name);
}
public ScriptMethod getFoundsetMethod(String name)
{
if (name == null) return null;
return AbstractBase.selectByName(new TypeIterator<ScriptMethod>(getAllObjects(), IRepository.METHODS), name);
}
}