001package co.codewizards.cloudstore.local.db; 002 003import static co.codewizards.cloudstore.core.util.StringUtil.*; 004import static co.codewizards.cloudstore.local.db.DatabaseAdapterFactory.*; 005import static java.util.Objects.*; 006 007import java.util.ServiceLoader; 008import java.util.SortedMap; 009import java.util.TreeMap; 010 011import org.slf4j.Logger; 012import org.slf4j.LoggerFactory; 013 014import co.codewizards.cloudstore.core.config.ConfigImpl; 015 016public class DatabaseAdapterFactoryRegistry { 017 private static final Logger logger = LoggerFactory.getLogger(DatabaseAdapterFactoryRegistry.class); 018 019 private DatabaseAdapterFactory databaseAdapterFactory; 020 021 protected DatabaseAdapterFactoryRegistry() { } 022 023 private static final class Holder { 024 public static final DatabaseAdapterFactoryRegistry instance = new DatabaseAdapterFactoryRegistry(); 025 } 026 027 public static DatabaseAdapterFactoryRegistry getInstance() { 028 return Holder.instance; 029 } 030 031 /** 032 * @deprecated Should normally only be used by tests. 033 */ 034 @Deprecated 035 public void clearCache() { 036 logger.info("clearCache: entered."); 037 databaseAdapterFactory = null; 038 } 039 040 public DatabaseAdapter createDatabaseAdapter() { 041 final DatabaseAdapterFactory databaseAdapterFactory= getDatabaseAdapterFactoryOrFail(); 042 final DatabaseAdapter databaseAdapter = databaseAdapterFactory.createDatabaseAdapter(); 043 if (databaseAdapter == null) 044 throw new IllegalStateException(String.format("databaseAdapterFactory.createDatabaseAdapter() returned null! Implementation error in %s!", 045 databaseAdapterFactory.getClass().getName())); 046 047 return databaseAdapter; 048 } 049 050 protected DatabaseAdapterFactory getDatabaseAdapterFactoryOrFail() { 051 DatabaseAdapterFactory databaseAdapterFactory = this.databaseAdapterFactory; 052 if (databaseAdapterFactory == null) { 053 final String databaseAdaptorName = ConfigImpl.getInstance().getPropertyAsNonEmptyTrimmedString( 054 CONFIG_KEY_DATABASE_ADAPTER_NAME, DEFAULT_DATABASE_ADAPTER_NAME); 055 056 final SortedMap<String, DatabaseAdapterFactory> name2DatabaseAdapter = getName2DatabaseAdapterFactory(); 057 if (name2DatabaseAdapter.isEmpty()) 058 throw new IllegalStateException("There is no DatabaseAdapterFactory registered!"); 059 060 if (isEmpty(databaseAdaptorName)) 061 databaseAdapterFactory = getDatabaseAdapterFactoryWithHighestPriority(name2DatabaseAdapter); 062 else { 063 databaseAdapterFactory = name2DatabaseAdapter.get(databaseAdaptorName); 064 if (databaseAdapterFactory == null) 065 throw new IllegalArgumentException(String.format("There is no DatabaseAdapterFactory with name='%s'!", databaseAdaptorName)); 066 } 067 068 this.databaseAdapterFactory = databaseAdapterFactory; 069 } 070 else 071 logger.debug("getDatabaseAdapterFactoryOrFail: returning existing DatabaseAdapterFactory instance."); 072 073 return databaseAdapterFactory; 074 } 075 076 private static SortedMap<String, DatabaseAdapterFactory> getName2DatabaseAdapterFactory() { 077 SortedMap<String, DatabaseAdapterFactory> result = new TreeMap<String, DatabaseAdapterFactory>(); 078 for (final DatabaseAdapterFactory a : ServiceLoader.load(DatabaseAdapterFactory.class)) { 079 final String name = a.getName(); 080 requireNonNull(name, String.format("%s.getName()", a.getClass().getName())); 081 if (name.indexOf(' ') >= 0) 082 throw new IllegalStateException( 083 String.format("%s.getName() returned a symbolic name containing a space!", a.getClass().getName())); 084 085 final DatabaseAdapterFactory old = result.put(name, a); 086 if (old != null) 087 throw new IllegalStateException( 088 String.format("There are multiple DatabaseAdapterFactory classes with name='%s'! %s + %s", 089 name, a.getClass().getName(), old.getClass().getName())); 090 } 091 return result; 092 } 093 094 private static DatabaseAdapterFactory getDatabaseAdapterFactoryWithHighestPriority(final SortedMap<String, DatabaseAdapterFactory> name2DatabaseAdapter) { 095 DatabaseAdapterFactory databaseAdapterFactory = null; 096 for (final DatabaseAdapterFactory a : name2DatabaseAdapter.values()) { 097 if (databaseAdapterFactory == null || databaseAdapterFactory.getPriority() < a.getPriority()) 098 databaseAdapterFactory = a; 099 } 100 return databaseAdapterFactory; 101 } 102}