All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.tentackle.i18n.pdo.StoredBundlePersistenceImpl Maven / Gradle / Ivy

There is a newer version: 21.16.1.0
Show newest version
/*
 * 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> 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