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

org.jaxdb.jsql.Connector Maven / Gradle / Ivy

/* Copyright (c) 2021 JAX-DB
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * You should have received a copy of The MIT License (MIT) along with this
 * program. If not, see .
 */

package org.jaxdb.jsql;

import static org.libj.lang.Assertions.*;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;

import org.jaxdb.jsql.Notification.Action;
import org.jaxdb.jsql.Notification.Action.DELETE;
import org.jaxdb.jsql.Notification.Action.INSERT;
import org.jaxdb.jsql.Notification.Action.UP;
import org.jaxdb.vendor.DbVendor;
import org.libj.sql.exception.SQLExceptions;
import org.libj.util.ConcurrentHashSet;

public class Connector implements ConnectionFactory {
  private static final ConcurrentHashMap>> initialized = new ConcurrentHashMap<>();

  private final Schema schema;
  private final Class schemaClass;

  private final ConnectionFactory connectionFactory;
  private final boolean isPrepared;
  private volatile Notifier notifier;

  protected Connector(final Schema schema, final ConnectionFactory connectionFactory, final boolean isPrepared) {
    this.schema = schema;
    this.schemaClass = schema.getClass();
    this.connectionFactory = assertNotNull(connectionFactory);
    this.isPrepared = isPrepared;
  }

  Schema getSchema() {
    return schema;
  }

  public boolean isPrepared() {
    return isPrepared;
  }

  Notifier getNotifier() {
    return notifier;
  }

  public boolean hasNotificationListener(final INSERT insert, final type.Table$ table) {
    return hasNotificationListener0(assertNotNull(insert), null, null, table);
  }

  public boolean hasNotificationListener(final UP up, final type.Table$ table) {
    return hasNotificationListener0(null, assertNotNull(up), null, table);
  }

  public boolean hasNotificationListener(final DELETE delete, final type.Table$ table) {
    return hasNotificationListener0(null, null, assertNotNull(delete), table);
  }

  public boolean hasNotificationListener(final INSERT insert, final UP up, final type.Table$ table) {
    return hasNotificationListener0(assertNotNull(insert), assertNotNull(up), null, table);
  }

  public boolean hasNotificationListener(final UP up, final DELETE delete, final type.Table$ table) {
    return hasNotificationListener0(null, assertNotNull(up), assertNotNull(delete), table);
  }

  public boolean hasNotificationListener(final INSERT insert, final DELETE delete, final type.Table$ table) {
    return hasNotificationListener0(assertNotNull(insert), null, assertNotNull(delete), table);
  }

  public boolean hasNotificationListener(final INSERT insert, final UP up, final DELETE delete, final type.Table$ table) {
    return hasNotificationListener0(assertNotNull(insert), assertNotNull(up), assertNotNull(delete), table);
  }

  private boolean hasNotificationListener0(final INSERT insert, final UP up, final DELETE delete, final type.Table$ table) {
    final Notifier notifier = this.notifier;
    return notifier != null && notifier.hasNotificationListener(insert, up, delete, (data.Table)table);
  }

  @SuppressWarnings("unchecked")
  public boolean addNotificationListener(final INSERT insert, final Notification.InsertListener notificationListener, final Queue> queue, final T ... tables) throws IOException, SQLException {
    return addNotificationListener0(assertNotNull(insert), null, null, assertNotNull(notificationListener), queue, assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public boolean addNotificationListener(final UP up, final Notification.UpdateListener notificationListener, final Queue> queue, final T ... tables) throws IOException, SQLException {
    return addNotificationListener0(null, assertNotNull(up), null, assertNotNull(notificationListener), queue, assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public boolean addNotificationListener(final DELETE delete, final Notification.DeleteListener notificationListener, final Queue> queue, final T ... tables) throws IOException, SQLException {
    return addNotificationListener0(null, null, assertNotNull(delete), assertNotNull(notificationListener), queue, assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public  & Notification.UpdateListener>boolean addNotificationListener(final INSERT insert, final UP up, final L notificationListener, final Queue> queue, final T ... tables) throws IOException, SQLException {
    return addNotificationListener0(assertNotNull(insert), assertNotNull(up), null, assertNotNull(notificationListener), queue, assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public  & Notification.DeleteListener>boolean addNotificationListener(final UP up, final DELETE delete, final L notificationListener, final Queue> queue, final T ... tables) throws IOException, SQLException {
    return addNotificationListener0(null, assertNotNull(up), assertNotNull(delete), assertNotNull(notificationListener), queue, assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public  & Notification.DeleteListener>boolean addNotificationListener(final INSERT insert, final DELETE delete, final L notificationListener, final Queue> queue, final T ... tables) throws IOException, SQLException {
    return addNotificationListener0(assertNotNull(insert), null, assertNotNull(delete), assertNotNull(notificationListener), queue, assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public  & Notification.UpdateListener & Notification.DeleteListener>boolean addNotificationListener(final INSERT insert, final UP up, final DELETE delete, final L notificationListener, final Queue> queue, final T ... tables) throws IOException, SQLException {
    return addNotificationListener0(assertNotNull(insert), assertNotNull(up), assertNotNull(delete), assertNotNull(notificationListener), queue, assertNotEmpty(tables));
  }

  @SuppressWarnings({"rawtypes", "resource", "unchecked"})
  boolean addNotificationListener0(final INSERT insert, final UP up, final DELETE delete, final Notification.Listener notificationListener, final Queue> queue, final T[] tables) throws IOException, SQLException {
    Notifier notifier = this.notifier;
    if (notifier == null) {
      synchronized (this) {
        notifier = this.notifier;
        if (notifier == null) {
          final Connection connection = connectionFactory.getConnection(null);
          final DbVendor vendor = DbVendor.valueOf(connection.getMetaData());
          if (vendor == DbVendor.POSTGRE_SQL) {
            this.notifier = notifier = new PostgreSQLNotifier(connection, this);
          }
          else {
            connection.close();
            throw new UnsupportedOperationException("Unsupported DbVendor: " + vendor);
          }
        }
      }
    }

    return notifier.addNotificationListener(insert, up, delete, notificationListener, (Queue)queue, tables);
  }

  public boolean removeNotificationListeners() throws IOException, SQLException {
    return removeNotificationListeners0(Action.INSERT, Action.UP, Action.DELETE);
  }

  public boolean removeNotificationListeners(final INSERT insert) throws IOException, SQLException {
    return removeNotificationListeners0(assertNotNull(insert), null, null);
  }

  public boolean removeNotificationListeners(final UP up) throws IOException, SQLException {
    return removeNotificationListeners0(null, assertNotNull(up), null);
  }

  public boolean removeNotificationListeners(final DELETE delete) throws IOException, SQLException {
    return removeNotificationListeners0(null, null, assertNotNull(delete));
  }

  public boolean removeNotificationListeners(final INSERT insert, final UP up) throws IOException, SQLException {
    return removeNotificationListeners0(assertNotNull(insert), assertNotNull(up), null);
  }

  public boolean removeNotificationListeners(final INSERT insert, final DELETE delete) throws IOException, SQLException {
    return removeNotificationListeners0(assertNotNull(insert), null, assertNotNull(delete));
  }

  public boolean removeNotificationListeners(final UP up, final DELETE delete) throws IOException, SQLException {
    return removeNotificationListeners0(null, assertNotNull(up), assertNotNull(delete));
  }

  public boolean removeNotificationListeners(final INSERT insert, final UP up, final DELETE delete) throws IOException, SQLException {
    return removeNotificationListeners0(assertNotNull(insert), assertNotNull(up), assertNotNull(delete));
  }

  private boolean removeNotificationListeners0(final INSERT insert, final UP up, final DELETE delete) throws IOException, SQLException {
    final Notifier notifier = this.notifier;
    return notifier != null && notifier.removeNotificationListeners(insert, up, delete);
  }

  @SuppressWarnings("unchecked")
  public boolean removeNotificationListeners(final INSERT insert, final T ... tables) throws IOException, SQLException {
    return removeNotificationListeners0(assertNotNull(insert), null, null, assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public boolean removeNotificationListeners(final UP up, final T ... tables) throws IOException, SQLException {
    return removeNotificationListeners0(null, assertNotNull(up), null, assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public boolean removeNotificationListeners(final DELETE delete, final T ... tables) throws IOException, SQLException {
    return removeNotificationListeners0(null, null, assertNotNull(delete), assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public boolean removeNotificationListeners(final INSERT insert, final UP up, final T ... tables) throws IOException, SQLException {
    return removeNotificationListeners0(assertNotNull(insert), assertNotNull(up), null, assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public boolean removeNotificationListeners(final INSERT insert, final DELETE delete, final T ... tables) throws IOException, SQLException {
    return removeNotificationListeners0(assertNotNull(insert), null, assertNotNull(delete), assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public boolean removeNotificationListeners(final UP up, final DELETE delete, final T ... tables) throws IOException, SQLException {
    return removeNotificationListeners0(null, assertNotNull(up), assertNotNull(delete), assertNotEmpty(tables));
  }

  @SuppressWarnings("unchecked")
  public boolean removeNotificationListeners(final INSERT insert, final UP up, final DELETE delete, final T ... tables) throws IOException, SQLException {
    return removeNotificationListeners0(assertNotNull(insert), assertNotNull(up), assertNotNull(delete), assertNotEmpty(tables));
  }

  private final boolean removeNotificationListeners0(final INSERT insert, final UP up, final DELETE delete, final T[] tables) throws IOException, SQLException {
    final Notifier notifier = this.notifier;
    return notifier != null && notifier.removeNotificationListeners(insert, up, delete, (data.Table[])tables);
  }

  @Override
  public Connection getConnection(final Transaction.Isolation isolation) throws IOException, SQLException {
    try {
      final Connection connection = connectionFactory.getConnection(isolation);
      final String url = connection.getMetaData().getURL();
      ConcurrentHashSet> schemas = initialized.get(url);
      if (schemas == null) {
        synchronized (initialized) {
          schemas = initialized.get(url);
          if (schemas == null) {
            initialized.put(url, schemas = new ConcurrentHashSet<>());
            schemas.add(schemaClass);
            final Compiler compiler = Compiler.getCompiler(DbVendor.valueOf(connection.getMetaData()));
            compiler.onConnect(connection);
            compiler.onRegister(connection);
            if (!connection.getAutoCommit())
              connection.commit();
          }
        }
      }
      else if (schemas.add(schemaClass)) {
        final Compiler compiler = Compiler.getCompiler(DbVendor.valueOf(connection.getMetaData()));
        compiler.onRegister(connection);
        if (!connection.getAutoCommit())
          connection.commit();
      }

      return connection;
    }
    catch (final SQLException e) {
      throw SQLExceptions.toStrongType(e);
    }
  }

  @Override
  public int hashCode() {
    return 31 + schema.hashCode();
  }

  @Override
  public boolean equals(final Object obj) {
    if (this == obj)
      return true;

    if (!(obj instanceof Connector))
      return false;

    final Connector that = (Connector)obj;
    return schema.equals(that.schema);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy