/*
* Copyright 2013 Gordon Burgett and individual contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xflatdb.xflat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.xflatdb.xflat.convert.PojoConverter;
import org.xflatdb.xflat.db.IdGenerator;
import org.xflatdb.xflat.db.BigIntIdGenerator;
import org.xflatdb.xflat.db.TimestampIdGenerator;
import org.xflatdb.xflat.db.UuidIdGenerator;
import org.xflatdb.xflat.db.XFlatDatabase;
/**
* The Configuration for a new XFlat Database.
* <br/>
* This Configuration must be
* passed to the {@link XFlatDatabase#setConfig(org.xflatdb.xflat.DatabaseConfig) }
* method before initialization, or the default values will be used.
* <p/>
* This class is immutable, all set methods return new objects.
* @author gordon
*/
public class DatabaseConfig {
private List<Class<? extends IdGenerator>> idGeneratorStrategy;
/**
* Gets the ID generator strategy used by this Database.
* <p/>
* ID generators are selected on a per-table basis by the {@link Database}
* based on an ID generation strategy. The strategy selects the first IdGenerator
* in the list that supports the ID property's type.
* @return An unmodifiable list of the ID generators in the strategy.
*/
public List<Class<? extends IdGenerator>> getIdGeneratorStrategy(){
if(idGeneratorStrategy == null){
return Collections.EMPTY_LIST;
}
return this.idGeneratorStrategy;
}
private int threadCount;
/**
* Gets the number of threads that this Database will spool up in its executor service.
* <p/>
* This is unused if an executor service is provided to the Database upon construction.
* @return the size of the database's thread pool
* @see #withThreadCount(int)
*/
public int getThreadCount(){
return this.threadCount;
}
private String pojoConverterClass;
/**
* Gets the binary name of the class used by the database to automatically map
* and convert POJOs to XML for the database. This class must implement
* {@link PojoConverter}.
* <p/>
* The database will load this class using its {@link ClassLoader} in order
* to convert pojos. This is kept as a string because the POJO converter
* class may not need to be loaded, so you can exclude the JARs from the
* classpath if you desire.
* @return The binary name of the class which will be loaded in order to
* automatically map POJOs for conversion to XML.
*/
public String getPojoConverterClass(){
return this.pojoConverterClass;
}
private TableConfig defaultTableConfig;
/**
* Creates a new DatabaseConfig with the default values.
*/
public DatabaseConfig(){
this.threadCount = 4;
this.pojoConverterClass = "org.xflatdb.xflat.convert.converters.JAXBPojoConverter";
this.defaultTableConfig = new TableConfig();
this.idGeneratorStrategy = Arrays.asList(
UuidIdGenerator.class,
BigIntIdGenerator.class,
TimestampIdGenerator.class
);
}
private DatabaseConfig(DatabaseConfig other){
this.threadCount = other.threadCount;
this.pojoConverterClass = other.pojoConverterClass;
//straight assignment is OK cause they are immutable.
this.defaultTableConfig = other.defaultTableConfig;
//straight assignment is OK cause they are unmodifiable lists of immutable objects.
this.idGeneratorStrategy = other.idGeneratorStrategy;
}
/**
* Sets the ID generator strategy used by this Database.
* <p/>
* ID generators are selected on a per-table basis by the {@link Database}
* based on an ID generation strategy. The strategy selects the first IdGenerator
* in the list that supports the ID property's type.
* @param strategy The strategy to use for this database.
* @return A new instance of the DatabaseConfig using this strategy.
*/
public DatabaseConfig withIdGeneratorStrategy(List<Class<? extends IdGenerator>> strategy){
if(strategy.size() <= 0){
throw new IllegalArgumentException("Id Generator strategy must contain at least " +
"one ID generator");
}
DatabaseConfig ret = new DatabaseConfig(this);
ret.idGeneratorStrategy = Collections.unmodifiableList(new ArrayList<>(strategy));
return ret;
}
/**
* Sets the number of threads that this Database will spool up in its executor service.
* <p/>
* The database uses an ExecutorService to manage scheduled and recurring tasks.
* This sets the size of its thread pool.<br/>
* This is unused if an executor service is provided to the Database upon construction.
* @param threadCount The number of threads in the database's thread pool.
* @return A new instance with the ThreadCount property set.
*/
public DatabaseConfig withThreadCount(int threadCount){
DatabaseConfig ret = new DatabaseConfig(this);
ret.threadCount = threadCount;
return ret;
}
/**
* Sets the binary name of the class used by the database to convert
* POJOs for the database. The class MUST be an implementation of
* {@link PojoConverter}. This class is only loaded when needed, in order
* to avoid requiring JARs that are unnecessary.
*
* The default value is a JAXB-based implementation. If the PojoConverter
* is never used, the JAXB context will never be loaded, and the JAXB jars
* will not be necessary on the classpath.
* @param className
* @return A new instance with the pojoConverterClass property set.
*/
public DatabaseConfig withPojoConverterClass(String className){
DatabaseConfig ret = new DatabaseConfig(this);
ret.pojoConverterClass = className;
return ret;
}
public TableConfig getDefaultTableConfig(){
return this.defaultTableConfig;
}
/**
* Sets the {@link TableConfig} used for new tables that have not been
* manually configured.
* If {@link Database#getTable(java.lang.Class) } is called
* for a table that has not been manually configured using
* {@link XFlatDatabase#configureTable(java.lang.String, org.xflatdb.xflat.TableConfig) },
* this configuration is used.
* @param tableConfig The default table config to use.
* @return A new instance with the defaultTableConfig property set.
*/
public DatabaseConfig withDefaultTableConfig(TableConfig tableConfig){
DatabaseConfig ret = new DatabaseConfig(this);
ret.defaultTableConfig = tableConfig;
return ret;
}
/**
* Gets the default database config. Equivalent to instantiating
* a new instance, but this is a singleton.
*/
public static DatabaseConfig DEFAULT = new DatabaseConfig();
@Override
public int hashCode() {
int hash = 3;
hash = 43 * hash + this.threadCount;
hash = 43 * hash + Objects.hashCode(this.pojoConverterClass);
hash = 43 * hash + Objects.hashCode(this.defaultTableConfig);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DatabaseConfig other = (DatabaseConfig) obj;
if(this.idGeneratorStrategy == null){
if(other.idGeneratorStrategy != null)
return false;
}
else{
if(other.idGeneratorStrategy == null){
return false;
}
if(this.idGeneratorStrategy.size() != other.idGeneratorStrategy.size()){
return false;
}
for(int i = 0; i < this.idGeneratorStrategy.size(); i++){
if(!Objects.equals(this.idGeneratorStrategy.get(i), other.idGeneratorStrategy.get(i)))
return false;
}
}
if (this.threadCount != other.threadCount) {
return false;
}
if (!Objects.equals(this.pojoConverterClass, other.pojoConverterClass)) {
return false;
}
if (!Objects.equals(this.defaultTableConfig, other.defaultTableConfig)) {
return false;
}
return true;
}
}