org.tentackle.persist.DbPreferencesKey Maven / Gradle / Ivy
/**
* Tentackle - http://www.tentackle.org
*
* This library 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 2.1 of the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.tentackle.persist;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.tentackle.pdo.ClassId;
import org.tentackle.pdo.ModificationEvent;
import org.tentackle.pdo.ModificationListenerAdapter;
import org.tentackle.pdo.PdoTracker;
import org.tentackle.pdo.PersistenceException;
import org.tentackle.pdo.TableName;
import org.tentackle.persist.rmi.DbPreferencesKeyRemoteDelegate;
import org.tentackle.prefs.PersistedPreferencesFactory;
import org.tentackle.sql.Backend;
/**
* @> $mapfile
*
* # a preferences key/value pair
* name := $classname
* id := $classid
* table := $tablename
*
* ## attributes
* [remote, tableserial]
*
* long nodeId nodeid ID of the preferences node
* String(128) key pkey name of the key
* String(255) value pvalue value of the key
*
* ## indexes
* unique index path := nodeid, pkey
* index tableserial := tableserial
*
* @<
*/
/**
* A preferences key/value pair stored in the database.
*
* @author harald
*/
@ClassId(/**/4/**/) // @wurblet < Inject $classid
@TableName(/**/"prefkey"/**/) // @wurblet < Inject --string $tablename
public class DbPreferencesKey extends AbstractDbObject {
private static final long serialVersionUID = 5733105489734329678L;
/** the database tablename. */
public static final String TABLENAME = /**/"prefkey"/**/; // @wurblet < Inject --string $tablename
private static final DbObjectClassVariables CLASSVARIABLES =
new DbObjectClassVariables<>(DbPreferencesKey.class,
/**/4/**/, // @wurblet < Inject $classid
TABLENAME);
static {
// register updater for sync between jvms
PdoTracker.getInstance().addModificationListener(new ModificationListenerAdapter(TABLENAME) {
@Override
public void dataChanged(ModificationEvent ev) {
DbPreferencesFactory factory = (DbPreferencesFactory) PersistedPreferencesFactory.getInstance();
if (factory.isAutoSync()) {
factory.expireKeys(ev.getSerial());
}
}
});
}
/**
* if node is "new", the childs won't get a valid node id.
* Instead they are linked to the node by an object reference.
*/
private DbPreferencesNode lazyNode;
/**
* Creates a preferences key.
*
* @param db the db connection
*/
public DbPreferencesKey (Db db) {
super(db);
}
/**
* Creates a preferences key (without db connection).
*/
public DbPreferencesKey() {
super();
}
@Override
public String toString() {
return (lazyNode != null ? ("(node: " + lazyNode + ")") : ("nodeId=" + nodeId)) + ", key='" + key + "', value='" + value + "'";
}
@Override
public boolean isCountingModification(char modType) {
return true;
}
/**
* sets the "lazy" parent, i.e. a new parent without an ID.
*
* @param node the parent node, null if none.
*/
public void setLazyNode(DbPreferencesNode node) {
this.lazyNode = node;
}
/**
* @return the lazy parent, if any
*/
public DbPreferencesNode getLazyNode() {
return lazyNode;
}
/**
* {@inheritDoc}
*
* Overridden to set the parent id if lazy parent set and has no id
*/
@Override
public void prepareSetFields() {
if (nodeId == 0) {
if (lazyNode != null) {
nodeId = lazyNode.getId();
if (nodeId == 0) {
lazyNode.saveObject();
nodeId = lazyNode.getId();
}
}
}
}
@Override
public DbObjectClassVariables getClassVariables() {
return CLASSVARIABLES;
}
/**
* Gets all keys belonging to a node.
*
* @param nodeId the node's ID
* @return List of keys
*
* @wurblet selectByNodeId DbSelectList --model=$mapfile nodeId
*/
// //GEN-BEGIN:selectByNodeId
public List selectByNodeId(long nodeId) {
if (getSession().isRemote()) {
// invoke remote method
try {
List list = ((DbPreferencesKeyRemoteDelegate) getRemoteDelegate()).
selectByNodeId(nodeId);
getSession().applyTo(list);
return list;
}
catch (RemoteException e) {
throw PersistenceException.createFromRemoteException(getSession(), e);
}
}
// else: local mode
PreparedStatementWrapper st = getPreparedStatement(SELECT_BY_NODE_ID_STMT,
() -> {
StringBuilder sql = createSelectAllInnerSql();
sql.append(Backend.SQL_AND);
sql.append(CN_NODEID);
sql.append(Backend.SQL_EQUAL_PAR);
getBackend().buildSelectSql(sql, false, 0, 0);
return sql.toString();
}
);
int ndx = 1;
st.setLong(ndx++, nodeId);
try (ResultSetWrapper rs = st.executeQuery()) {
List list = new ArrayList<>();
boolean derived = getClass() != DbPreferencesKey.class;
while (rs.next()) {
DbPreferencesKey obj = derived ? newInstance() : new DbPreferencesKey(getSession());
obj = obj.readFromResultSetWrapper(rs);
if (obj != null) {
list.add(obj);
}
}
return list;
}
}
private static final StatementId SELECT_BY_NODE_ID_STMT = new StatementId();
// //GEN-END:selectByNodeId
/**
* Get a preferences key by nodeid and key name.
*
* @param nodeId the node ID
* @param key the key name
* @return the preferences key, null if not found
*
* @wurblet selectByNodeIdKey DbSelectUnique --model=$mapfile nodeId key
*/
// //GEN-BEGIN:selectByNodeIdKey
public DbPreferencesKey selectByNodeIdKey(long nodeId, String key) {
if (getSession().isRemote()) {
// invoke remote method
try {
DbPreferencesKey obj = ((DbPreferencesKeyRemoteDelegate) getRemoteDelegate()).
selectByNodeIdKey(nodeId, key);
getSession().applyTo(obj);
return obj;
}
catch (RemoteException e) {
throw PersistenceException.createFromRemoteException(this, e);
}
}
// else: local mode
PreparedStatementWrapper st = getPreparedStatement(SELECT_BY_NODE_ID_KEY_STMT,
() -> {
StringBuilder sql = createSelectAllInnerSql();
sql.append(Backend.SQL_AND);
sql.append(CN_NODEID);
sql.append(Backend.SQL_EQUAL_PAR);
sql.append(Backend.SQL_AND);
sql.append(CN_KEY);
sql.append(Backend.SQL_EQUAL_PAR);
getBackend().buildSelectSql(sql, false, 0, 0);
return sql.toString();
}
);
int ndx = 1;
st.setLong(ndx++, nodeId);
st.setString(ndx++, key);
try (ResultSetWrapper rs = st.executeQuery()) {
if (rs.next()) {
return readFromResultSetWrapper(rs);
}
return null; // not found
}
}
private static final StatementId SELECT_BY_NODE_ID_KEY_STMT = new StatementId();
// //GEN-END:selectByNodeIdKey
/**
* Deletes all keys for a node.
*
* @param nodeId the node's ID
* @return the number of keys deleted
*
* @wurblet deleteByNodeId DbDeleteBy --model=$mapfile nodeId
*/
// //GEN-BEGIN:deleteByNodeId
public int deleteByNodeId(long nodeId) {
if (getSession().isRemote()) {
try {
return ((DbPreferencesKeyRemoteDelegate) getRemoteDelegate()).
deleteByNodeId(nodeId);
}
catch (RemoteException e) {
throw PersistenceException.createFromRemoteException(getSession(), e);
}
}
// else: local mode
PreparedStatementWrapper st = getPreparedStatement(DELETE_BY_NODE_ID_STMT,
() -> {
StringBuilder sql = createDeleteAllSql();
sql.append(Backend.SQL_AND);
sql.append(CN_NODEID);
sql.append(Backend.SQL_EQUAL_PAR);
return sql.toString();
}
);
int ndx = 1;
st.setLong(ndx++, nodeId);
return st.executeUpdate();
}
private static final StatementId DELETE_BY_NODE_ID_STMT = new StatementId();
// //GEN-END:deleteByNodeId
// @wurblet methods MethodsImpl --tracked --noif --model=$mapfile
// //GEN-BEGIN:methods
/**
* Object provides the tableserial.
* @return true
*/
@Override
public boolean isTableSerialProvided() {
return true;
}
/**
* Overridden cause of "--tracked".
* @return true = setters check for modification
*/
@Override
public boolean isTracked() {
return true; // invoking isModified() is ok
}
@Override
public void getFields(ResultSetWrapper rs) {
super.getFields(rs);
if (rs.configureSection(CLASSVARIABLES)) {
rs.configureColumn(CN_TABLESERIAL);
rs.configureColumn(CN_NODEID);
rs.configureColumn(CN_KEY);
rs.configureColumn(CN_VALUE);
rs.configureColumn(CN_ID);
rs.configureColumn(CN_SERIAL);
}
if (rs.getRow() <= 0) {
throw new PersistenceException(getSession(), "no valid row");
}
setTableSerial(rs.getLong());
nodeId = rs.getLong();
key = rs.getString();
value = rs.getString();
setId(rs.getLong());
setSerial(rs.getLong());
}
@Override
public int setFields(PreparedStatementWrapper st) {
int ndx = super.setFields(st);
st.setLong(++ndx, getTableSerial());
st.setLong(++ndx, nodeId);
st.setString(++ndx, key);
st.setString(++ndx, value);
st.setLong(++ndx, getId());
st.setLong(++ndx, getSerial());
return ndx;
}
@Override
public String createInsertSql() {
return Backend.SQL_INSERT_INTO + getTableName() + Backend.SQL_LEFT_PARENTHESIS +
CN_TABLESERIAL + Backend.SQL_COMMA +
CN_NODEID + Backend.SQL_COMMA +
CN_KEY + Backend.SQL_COMMA +
CN_VALUE + Backend.SQL_COMMA +
CN_ID + Backend.SQL_COMMA +
CN_SERIAL +
Backend.SQL_INSERT_VALUES +
Backend.SQL_PAR_COMMA +
Backend.SQL_PAR_COMMA +
Backend.SQL_PAR_COMMA +
Backend.SQL_PAR_COMMA +
Backend.SQL_PAR_COMMA +
Backend.SQL_PAR + Backend.SQL_RIGHT_PARENTHESIS;
}
@Override
public String createUpdateSql() {
return Backend.SQL_UPDATE + getTableName() + Backend.SQL_SET +
CN_TABLESERIAL + Backend.SQL_EQUAL_PAR_COMMA +
CN_NODEID + Backend.SQL_EQUAL_PAR_COMMA +
CN_KEY + Backend.SQL_EQUAL_PAR_COMMA +
CN_VALUE + Backend.SQL_EQUAL_PAR_COMMA +
CN_SERIAL + Backend.SQL_EQUAL + CN_SERIAL + Backend.SQL_PLUS_ONE +
Backend.SQL_WHERE + CN_ID + Backend.SQL_EQUAL_PAR +
Backend.SQL_AND + CN_SERIAL + Backend.SQL_EQUAL_PAR;
}
/**
* Gets the attribute nodeId.
*
* @return ID of the preferences node
*/
public long getNodeId() {
return nodeId;
}
/**
* Sets the attribute nodeId.
*
* @param nodeId ID of the preferences node
*/
public void setNodeId(long nodeId) {
assertMutable();
if (this.nodeId != nodeId) {
setModified(true);
}
this.nodeId = nodeId;
}
/**
* Gets the attribute key.
*
* @return name of the key
*/
public String getKey() {
return key;
}
/**
* Sets the attribute key.
*
* @param key name of the key
*/
public void setKey(String key) {
assertMutable();
if (!Objects.equals(this.key, key)) {
setModified(true);
}
this.key = key;
}
/**
* Gets the attribute value.
*
* @return value of the key
*/
public String getValue() {
return value;
}
/**
* Sets the attribute value.
*
* @param value value of the key
*/
public void setValue(String value) {
assertMutable();
if (!Objects.equals(this.value, value)) {
setModified(true);
}
this.value = value;
}
// //GEN-END:methods
// record members
// @wurblet declare Declare --model=$mapfile
// //GEN-BEGIN:declare
/** ID of the preferences node. */
private long nodeId;
/** name of the key. */
private String key;
/** value of the key. */
private String value;
// //GEN-END:declare
// @wurblet fieldNames ColumnNames --model=$mapfile
// //GEN-BEGIN:fieldNames
/** database column name for 'nodeId'. */
public static final String CN_NODEID = "nodeid";
/** database column name for 'key'. */
public static final String CN_KEY = "pkey";
/** database column name for 'value'. */
public static final String CN_VALUE = "pvalue";
// //GEN-END:fieldNames
}