org.tentackle.i18n.pdo.StoredBundlePersistenceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tentackle-i18n Show documentation
Show all versions of tentackle-i18n Show documentation
I18N provider to use StoredBundle instead of ResourceBundle
/*
* Tentackle - https://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.i18n.pdo;
import org.tentackle.dbms.ModificationType;
import org.tentackle.dbms.PreparedStatementWrapper;
import org.tentackle.dbms.ResultSetWrapper;
import org.tentackle.dbms.StatementId;
import org.tentackle.i18n.pdo.rmi.StoredBundleRemoteDelegate;
import org.tentackle.misc.IdentifiableMap;
import org.tentackle.misc.TrackedArrayList;
import org.tentackle.misc.TrackedList;
import org.tentackle.pdo.DomainContext;
import org.tentackle.pdo.Pdo;
import org.tentackle.pdo.PdoCache;
import org.tentackle.pdo.PdoCacheIndex;
import org.tentackle.pdo.PersistentDomainObject;
import org.tentackle.pdo.PersistentObjectService;
import org.tentackle.persist.AbstractPersistentObject;
import org.tentackle.persist.Join;
import org.tentackle.persist.JoinedSelect;
import org.tentackle.persist.PersistentObjectClassVariables;
import org.tentackle.session.PersistenceException;
import org.tentackle.session.Session;
import org.tentackle.sql.Backend;
import org.tentackle.sql.JoinType;
import org.tentackle.validate.ValidationFailedException;
import org.tentackle.validate.ValidationResult;
import org.tentackle.validate.ValidationScope;
import org.tentackle.validate.ValidationUtilities;
import java.io.Serial;
import java.rmi.RemoteException;
import java.util.List;
import java.util.Objects;
/**
* Number Space persistence implementation.
*
* @author harald
*/
@PersistentObjectService(StoredBundle.class)
public class StoredBundlePersistenceImpl extends AbstractPersistentObject implements StoredBundlePersistence {
@Serial
private static final long serialVersionUID = 1L;
// @wurblet classVariables ClassVariables
////GEN-BEGIN:classVariables
/** Variables common to all instances of StoredBundlePersistenceImpl. */
@SuppressWarnings({"unchecked", "rawtypes"})
public static final PersistentObjectClassVariables CLASSVARIABLES =
PersistentObjectClassVariables.create(
StoredBundle.class,
StoredBundlePersistenceImpl.class,
"bndl",
null,
List.of(
new Join<>(JoinType.LEFT, "bndl.id", "e_1.bundle_id", StoredBundleKey.class, "e_1",
(bndl, bkey) -> {
((StoredBundlePersistenceImpl) bndl.getPersistenceDelegate()).getKeysBlunt().addBlunt(bkey);
((StoredBundleKeyPersistenceImpl) bkey.getPersistenceDelegate()).setBundleBlunt(bndl);
}
)
)
);
@Override
public PersistentObjectClassVariables getClassVariables() {
return CLASSVARIABLES;
}
// //GEN-END:classVariables
// @wurblet fieldnames ColumnNames
////GEN-BEGIN:fieldnames
/** database column name for 'name'. */
public static final String CN_NAME = "bname";
/** database column name for 'locale'. */
public static final String CN_LOCALE = "blocale";
// //GEN-END:fieldnames
// @wurblet declare Declare
////GEN-BEGIN:declare
/** the resource bundle name. */
private String name;
/** the locale, null if default. */
private String locale;
// //GEN-END:declare
/**
* Creates a number space.
*
* @param pdo the number space PDO
* @param context the domain context
*/
public StoredBundlePersistenceImpl (StoredBundle pdo, DomainContext context) {
super(pdo, context);
}
/**
* Creates a number space with a session only.
*
* @param pdo the number space PDO
* @param session the session
*/
public StoredBundlePersistenceImpl(StoredBundle pdo, Session session) {
super(pdo, session);
}
/**
* Creates a number space without domain context or session.
*
* @param pdo the number space PDO
*/
public StoredBundlePersistenceImpl(StoredBundle pdo) {
super(pdo);
}
/**
* Creates a number space without domain context or session.
*/
public StoredBundlePersistenceImpl() {
super();
}
// @wurblet methods MethodsImpl
////GEN-BEGIN:methods
@Override
public StoredBundleRemoteDelegate getRemoteDelegate() {
return (StoredBundleRemoteDelegate) super.getRemoteDelegate();
}
@Override
public boolean isRootEntity() {
return true;
}
@Override
public boolean isTableSerialProvided() {
return true;
}
@Override
public boolean isTracked() {
return true;
}
@Override
public void getFields(ResultSetWrapper rs) {
super.getFields(rs);
if (rs.configureSection(CLASSVARIABLES)) {
rs.configureColumn(CN_TABLESERIAL);
rs.configureColumn(CN_NAME);
rs.configureColumn(CN_LOCALE);
rs.configureColumn(CN_ID);
rs.configureColumn(CN_SERIAL);
}
setTableSerial(rs.getLong());
name = rs.getString();
locale = rs.getString(true);
setId(rs.getLong());
setSerial(rs.getLong());
}
@Override
public int setFields(PreparedStatementWrapper st) {
int ndx = super.setFields(st);
st.setLong(++ndx, getTableSerial());
st.setString(++ndx, name);
st.setString(++ndx, locale, true);
st.setLong(++ndx, getId());
st.setLong(++ndx, getSerial());
return ndx;
}
@Override
public String createInsertSql(Backend backend) {
return Backend.SQL_INSERT_INTO + getTableName() + Backend.SQL_LEFT_PARENTHESIS +
CN_TABLESERIAL + Backend.SQL_COMMA +
CN_NAME + Backend.SQL_COMMA +
CN_LOCALE + Backend.SQL_COMMA +
CN_ID + Backend.SQL_COMMA +
CN_SERIAL +
Backend.SQL_INSERT_VALUES +
Backend.SQL_PAR_COMMA.repeat(4) +
Backend.SQL_PAR + Backend.SQL_RIGHT_PARENTHESIS;
}
@Override
public String createUpdateSql(Backend backend) {
return Backend.SQL_UPDATE + getTableName() + Backend.SQL_SET +
CN_TABLESERIAL + Backend.SQL_EQUAL_PAR_COMMA +
CN_NAME + Backend.SQL_EQUAL_PAR_COMMA +
CN_LOCALE + 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;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
if (!Objects.equals(this.name, name)) {
setModified(true);
this.name = name;
}
}
@Override
public String getLocale() {
return locale;
}
@Override
public void setLocale(String locale) {
if (!Objects.equals(this.locale, locale)) {
setModified(true);
this.locale = locale;
}
}
/**
* Copies all attributes from a snapshot back to this object.
*
* @param snapshot the snapshot object
*/
protected void revertAttributesToSnapshot(StoredBundlePersistenceImpl snapshot) {
super.revertAttributesToSnapshot(snapshot);
name = snapshot.name;
locale = snapshot.locale;
}
// selects by unique domain key
// @wurblet selectByUniqueDomainKey PdoSelectUnique name locale
// //GEN-END:methods
////GEN-BEGIN:selectByUniqueDomainKey
@Override
public StoredBundle selectByUniqueDomainKey(String name, String locale) {
if (getSession().isRemote()) {
try {
StoredBundle obj = getRemoteDelegate().selectByUniqueDomainKey(getDomainContext(), name, locale);
configureRemoteObject(getDomainContext(), obj);
return obj;
}
catch (RemoteException e) {
throw PersistenceException.createFromRemoteException(this, e);
}
}
PreparedStatementWrapper st = getPreparedStatement(SELECT_BY_UNIQUE_DOMAIN_KEY_STMT,
b -> {
StringBuilder sql = createSelectAllInnerSql(b);
sql.append(Backend.SQL_AND);
sql.append(getColumnName(CN_NAME));
sql.append(Backend.SQL_EQUAL_PAR);
sql.append(Backend.SQL_AND);
sql.append(getColumnName(CN_LOCALE));
sql.append(Backend.SQL_EQUAL_PAR);
b.buildSelectSql(sql, false, 0, 0);
return sql.toString();
}
);
int ndx = 1;
st.setString(ndx++, name);
st.setString(ndx, locale, true);
return executeFirstPdoQuery(st);
}
private static final StatementId SELECT_BY_UNIQUE_DOMAIN_KEY_STMT = new StatementId();
// //GEN-END:selectByUniqueDomainKey
// @wurblet relations PdoRelations
////GEN-BEGIN:relations
// composite list of StoredBundleKey keys via StoredBundleKey#bundleId (Keys)
private TrackedList keys;
private boolean keysLoaded;
private transient TrackedList keysSnapshot;
@Override
public TrackedList getKeys() {
if (!keysLoaded) {
keys = isNew() ? new TrackedArrayList<>(false) : on(StoredBundleKey.class).selectByBundleId(getId());
for (StoredBundleKey obj: keys) {
obj.setBundle(me());
}
if (isImmutable()) {
keys.setImmutable(true);
}
keysLoaded = true;
}
return keys;
}
/**
* Gets keys without performing a select if not loaded.
*
* @return keys Keys
*/
public TrackedList getKeysBlunt() {
if (!keysLoaded) {
keys = new TrackedArrayList<>(false);
if (isImmutable()) {
keys.setImmutable(true);
}
keysLoaded = true;
}
return keys;
}
@Override
public boolean isKeysLoaded() {
return keysLoaded;
}
@Override
public void setSession(Session session) {
super.setSession(session);
session.applyTo(keys);
}
@Override
public void setDomainContext(DomainContext context) {
super.setDomainContext(context);
context.applyTo(keys);
}
/**
* Deletes all referencing composite relations that have been removed from the PDO.
* The database cascades down via referential integrity.
*/
public void deleteRemovedReferencingRelations() {
if (keys != null && keys.isSomeRemoved()) {
delete(keys.getRemovedObjects());
}
}
@Override
public void saveReferencingRelations(boolean update) {
super.saveReferencingRelations(update);
if (update) {
deleteRemovedReferencingRelations();
}
if (keys != null) {
getDomainContext().applyTo(keys);
for (StoredBundleKey obj: keys) {
obj.setBundle(me());
}
save(keys, true);
}
}
@Override
public List validate(String validationPath, ValidationScope scope) {
List results = super.validate(validationPath, scope);
try {
if (keys != null) {
results.addAll(ValidationUtilities.getInstance().validateCollection(
keys, validationPath + ".keys", scope));
}
}
catch (ValidationFailedException vfx) {
vfx.reThrow(results);
}
return results;
}
@Override
public void setImmutable(boolean immutable) {
super.setImmutable(immutable);
if (keys != null) {
keys.setImmutable(immutable);
}
}
@Override
public boolean isModified() {
return super.isModified()
|| isModified(keys)
;
}
@Override
public boolean isComposite() {
return true;
}
@Override
public IdentifiableMap extends PersistentDomainObject>> loadComponents(boolean onlyLoaded) {
IdentifiableMap> components = new IdentifiableMap<>();
addComponents(components, onlyLoaded);
return components;
}
@Override
public int addComponents(IdentifiableMap> components, boolean onlyLoaded) {
int count = 0;
count += super.addComponents(components, onlyLoaded);
if (!onlyLoaded || keysLoaded) {
count += addComponents(components, getKeys(), onlyLoaded);
}
return count;
}
@Override
public void insertPlainWithComponents() {
insertPlain();
insertPlainWithComponents(getKeys());
}
@Override
public void deletePlainWithComponents() {
// components are deleted via database referential integrity constraints
deletePlain();
}
@Override
public void markDeleted() {
super.markDeleted();
markDeleted(keys);
}
/**
* Updates the components in snapshot object.
* The snapshot object is assumed to be a clone of this object.
*
* @param snapshot the snapshot
*/
protected void createComponentsInSnapshot(StoredBundlePersistenceImpl snapshot) {
super.createComponentsInSnapshot(snapshot);
snapshot.keysSnapshot = TrackedList.createSnapshot(keys);
}
/**
* Reverts all components of this object to a given snapshot.
*
* @param snapshot the snapshot object
*/
protected void revertComponentsToSnapshot(StoredBundlePersistenceImpl snapshot) {
super.revertComponentsToSnapshot(snapshot);
keys = TrackedList.revertToSnapshot(keys, snapshot.keysSnapshot);
keysLoaded = snapshot.keysLoaded;
}
// //GEN-END:relations
// @wurblet cache PdoCache --preload --udk
////GEN-BEGIN:cache
/** Holder of the PDO cache singleton. */
private static class CacheHolder {
private static final PdoCache CACHE = createCache();
private static final PdoCacheIndex UDK_INDEX = createUdkIndex();
private static PdoCache createCache() {
PdoCache cache = Pdo.createPdoCache(StoredBundle.class, true, true, false);
Pdo.listen(cache::expire, StoredBundle.class);
return cache;
}
private static PdoCacheIndex createUdkIndex() {
return new PdoCacheIndex<>("StoredBundle:UDK") {
@Override
public StoredBundle select(DomainContext context, StoredBundle.StoredBundleUDK udk) {
return Pdo.create(StoredBundle.class, context).selectByUniqueDomainKeyForCache(udk);
}
@Override
public StoredBundle.StoredBundleUDK extract(StoredBundle pdo) {
return pdo.getUniqueDomainKey();
}
};
}
}
@Override
public PdoCache getCache() {
return CacheHolder.CACHE;
}
@Override
public boolean isCountingModification(ModificationType modType) {
return true;
}
@Override
public boolean isReadAllowed() {
return true;
}
@Override
public void expireCache(long maxSerial) {
super.expireCache(maxSerial);
CacheHolder.CACHE.expire(null, getTableName(), maxSerial);
}
@Override
public StoredBundle selectCachedOnly(long id) {
return getCache().select(getDomainContext(), id, false);
}
@Override
public StoredBundle selectCached(long id) {
return getCache().select(getDomainContext(), id);
}
/**
* Gets the index for the unique domain key.
*
* @return the index for StoredBundle.StoredBundleUDK udk
*/
protected PdoCacheIndex getCacheIndexUdk() {
return CacheHolder.UDK_INDEX;
}
/**
* Selects from cache by unique domain key but does not load from db if not in cache.
*
* @param udk the unique domain key
* @return the pdo, null if not in cache
*/
@Override
public StoredBundle selectCachedOnlyByUniqueDomainKey(StoredBundle.StoredBundleUDK udk) {
return getCache().select(getCacheIndexUdk(), getDomainContext(), udk, false);
}
/**
* Selects via cache by unique domain key.
*
* @param udk the unique key
* @return the pdo, null if no such object
*/
@Override
public StoredBundle selectCachedByUniqueDomainKey(StoredBundle.StoredBundleUDK udk) {
return getCache().select(getCacheIndexUdk(), getDomainContext(), udk);
}
/**
* Selects via remote cache, if session is remote.
*
* @param udk the unique key
* @return the pdo, null if no such object
*/
@Override
public StoredBundle selectByUniqueDomainKeyForCache(StoredBundle.StoredBundleUDK udk) {
StoredBundle obj;
if (getSession().isRemote()) {
try {
DomainContext context = getDomainContext();
obj = getRemoteDelegate().selectByUniqueDomainKeyForCache(context, udk);
configureRemoteObject(context, obj);
}
catch (RemoteException e) {
throw PersistenceException.createFromRemoteException(this, e);
}
}
else {
obj = me().findByUniqueDomainKey(udk);
}
return obj;
}
@Override
public List selectAllCached() {
return getCache().selectAll(getDomainContext());
}
// //GEN-END:cache
// @wurblet findByName PdoSelectList name *Keys
////GEN-BEGIN:findByName
@Override
public TrackedList findByName(String name) {
if (getSession().isRemote()) {
try {
TrackedList list = getRemoteDelegate().findByName(getDomainContext(), name);
configureRemoteObjects(getDomainContext(), list);
return list;
}
catch (RemoteException e) {
throw PersistenceException.createFromRemoteException(this, e);
}
}
JoinedSelect js = new JoinedSelect()
.addJoin(
new Join<>(JoinType.LEFT, getColumnName(CN_ID), "j_1.bundle_id", StoredBundleKey.class, "j_1",
(StoredBundle bndl, StoredBundleKey bkey) -> {
((StoredBundlePersistenceImpl) bndl.getPersistenceDelegate()).getKeysBlunt().addBlunt(bkey);
((StoredBundleKeyPersistenceImpl) bkey.getPersistenceDelegate()).setBundleBlunt(bndl);
}
)
);
PreparedStatementWrapper st = getPreparedStatement(FIND_BY_NAME_STMT,
b -> {
StringBuilder sql = createSelectAllInnerSql(b);
sql.append(Backend.SQL_AND);
sql.append(getColumnName(CN_NAME));
sql.append(Backend.SQL_EQUAL_PAR);
b.buildSelectSql(sql, false, 0, 0);
js.createJoinedSql(me(), sql);
return sql.toString();
}
);
int ndx = 1;
st.setString(ndx, name);
return executeTrackedListQuery(st, js);
}
private static final StatementId FIND_BY_NAME_STMT = new StatementId();
// //GEN-END:findByName
// @wurblet findByNameAndLocale PdoSelectUnique name locale *Keys
////GEN-BEGIN:findByNameAndLocale
@Override
public StoredBundle findByNameAndLocale(String name, String locale) {
if (getSession().isRemote()) {
try {
StoredBundle obj = getRemoteDelegate().findByNameAndLocale(getDomainContext(), name, locale);
configureRemoteObject(getDomainContext(), obj);
return obj;
}
catch (RemoteException e) {
throw PersistenceException.createFromRemoteException(this, e);
}
}
JoinedSelect js = new JoinedSelect()
.addJoin(
new Join<>(JoinType.LEFT, getColumnName(CN_ID), "j_1.bundle_id", StoredBundleKey.class, "j_1",
(StoredBundle bndl, StoredBundleKey bkey) -> {
((StoredBundlePersistenceImpl) bndl.getPersistenceDelegate()).getKeysBlunt().addBlunt(bkey);
((StoredBundleKeyPersistenceImpl) bkey.getPersistenceDelegate()).setBundleBlunt(bndl);
}
)
);
PreparedStatementWrapper st = getPreparedStatement(FIND_BY_NAME_AND_LOCALE_STMT,
b -> {
StringBuilder sql = createSelectAllInnerSql(b);
sql.append(Backend.SQL_AND);
sql.append(getColumnName(CN_NAME));
sql.append(Backend.SQL_EQUAL_PAR);
sql.append(Backend.SQL_AND);
sql.append(getColumnName(CN_LOCALE));
sql.append(Backend.SQL_EQUAL_PAR);
b.buildSelectSql(sql, false, 0, 0);
js.createJoinedSql(me(), sql);
return sql.toString();
}
);
int ndx = 1;
st.setString(ndx++, name);
st.setString(ndx, locale, true);
return executeFirstPdoQuery(st, js);
}
private static final StatementId FIND_BY_NAME_AND_LOCALE_STMT = new StatementId();
// //GEN-END:findByNameAndLocale
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy