package co.codewizards.cloudstore.local.db; import static co.codewizards.cloudstore.core.util.AssertUtil.*; import static co.codewizards.cloudstore.core.util.StringUtil.*; import static co.codewizards.cloudstore.local.db.DatabaseAdapterFactory.*; import java.util.ServiceLoader; import java.util.SortedMap; import java.util.TreeMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import co.codewizards.cloudstore.core.config.ConfigImpl; public class DatabaseAdapterFactoryRegistry { private static final Logger logger = LoggerFactory.getLogger(DatabaseAdapterFactoryRegistry.class); private DatabaseAdapterFactory databaseAdapterFactory; protected DatabaseAdapterFactoryRegistry() { } private static final class Holder { public static final DatabaseAdapterFactoryRegistry instance = new DatabaseAdapterFactoryRegistry(); } public static DatabaseAdapterFactoryRegistry getInstance() { return Holder.instance; } /** * @deprecated Should normally only be used by tests. */ @Deprecated public void clearCache() { logger.info("clearCache: entered."); databaseAdapterFactory = null; } public DatabaseAdapter createDatabaseAdapter() { final DatabaseAdapterFactory databaseAdapterFactory= getDatabaseAdapterFactoryOrFail(); final DatabaseAdapter databaseAdapter = databaseAdapterFactory.createDatabaseAdapter(); if (databaseAdapter == null) throw new IllegalStateException(String.format("databaseAdapterFactory.createDatabaseAdapter() returned null! Implementation error in %s!", databaseAdapterFactory.getClass().getName())); return databaseAdapter; } protected DatabaseAdapterFactory getDatabaseAdapterFactoryOrFail() { DatabaseAdapterFactory databaseAdapterFactory = this.databaseAdapterFactory; if (databaseAdapterFactory == null) { final String databaseAdaptorName = ConfigImpl.getInstance().getPropertyAsNonEmptyTrimmedString( CONFIG_KEY_DATABASE_ADAPTER_NAME, DEFAULT_DATABASE_ADAPTER_NAME); final SortedMap<String, DatabaseAdapterFactory> name2DatabaseAdapter = getName2DatabaseAdapterFactory(); if (name2DatabaseAdapter.isEmpty()) throw new IllegalStateException("There is no DatabaseAdapterFactory registered!"); if (isEmpty(databaseAdaptorName)) databaseAdapterFactory = getDatabaseAdapterFactoryWithHighestPriority(name2DatabaseAdapter); else { databaseAdapterFactory = name2DatabaseAdapter.get(databaseAdaptorName); if (databaseAdapterFactory == null) throw new IllegalArgumentException(String.format("There is no DatabaseAdapterFactory with name='%s'!", databaseAdaptorName)); } this.databaseAdapterFactory = databaseAdapterFactory; } else logger.debug("getDatabaseAdapterFactoryOrFail: returning existing DatabaseAdapterFactory instance."); return databaseAdapterFactory; } private static SortedMap<String, DatabaseAdapterFactory> getName2DatabaseAdapterFactory() { SortedMap<String, DatabaseAdapterFactory> result = new TreeMap<String, DatabaseAdapterFactory>(); for (final DatabaseAdapterFactory a : ServiceLoader.load(DatabaseAdapterFactory.class)) { final String name = a.getName(); assertNotNull(name, String.format("%s.getName()", a.getClass().getName())); if (name.indexOf(' ') >= 0) throw new IllegalStateException( String.format("%s.getName() returned a symbolic name containing a space!", a.getClass().getName())); final DatabaseAdapterFactory old = result.put(name, a); if (old != null) throw new IllegalStateException( String.format("There are multiple DatabaseAdapterFactory classes with name='%s'! %s + %s", name, a.getClass().getName(), old.getClass().getName())); } return result; } private static DatabaseAdapterFactory getDatabaseAdapterFactoryWithHighestPriority(final SortedMap<String, DatabaseAdapterFactory> name2DatabaseAdapter) { DatabaseAdapterFactory databaseAdapterFactory = null; for (final DatabaseAdapterFactory a : name2DatabaseAdapter.values()) { if (databaseAdapterFactory == null || databaseAdapterFactory.getPriority() < a.getPriority()) databaseAdapterFactory = a; } return databaseAdapterFactory; } }