nz.co.gregs.dbvolution.internal.properties.RowDefinitionInstanceWrapper Maven / Gradle / Ivy
package nz.co.gregs.dbvolution.internal.properties;
import java.util.ArrayList;
import java.util.List;
import nz.co.gregs.dbvolution.databases.DBDatabase;
import nz.co.gregs.dbvolution.DBReport;
import nz.co.gregs.dbvolution.DBRow;
import nz.co.gregs.dbvolution.annotations.DBTableName;
import nz.co.gregs.dbvolution.exceptions.DBRuntimeException;
import nz.co.gregs.dbvolution.query.RowDefinition;
/**
* Wraps a specific target object according to its type's
* {@link RowDefinitionClassWrapper}.
*
*
* To create instances of this type, call
* {@link RowDefinitionWrapperFactory#instanceWrapperFor(nz.co.gregs.dbvolution.query.RowDefinition)}
* on the appropriate {@link RowDefinition}.
*
*
* Instances of this class are lightweight and efficient to create, and they are
* intended to be short lived. Instances of this class must not be shared
* between different DBDatabase instances, however they can be safely associated
* within a single DBDatabase instance.
*
*
* Instances of this class are thread-safe.
*
*
Support DBvolution at
* Patreon
*
* @author Malcolm Lett
*/
public class RowDefinitionInstanceWrapper {
private final RowDefinitionClassWrapper classWrapper;
private final RowDefinition rowDefinition;
private final List allProperties;
private final List columnProperties;
private final List autoFillingProperties;
private final List foreignKeyProperties;
private final List primaryKeyProperties;
/**
* Called by
* {@link DBRowClassWrapper#instanceAdaptorFor(DBDefinition, Object)}.
*
*
* @param rowDefinition the target object of the same type as analyzed by
* {@code classWrapper}
*/
RowDefinitionInstanceWrapper(RowDefinitionClassWrapper classWrapper, RowDefinition rowDefinition) {
if (rowDefinition == null) {
throw new DBRuntimeException("Target object is null");
}
if (!classWrapper.adapteeClass().isInstance(rowDefinition)) {
throw new DBRuntimeException("Target object's type (" + rowDefinition.getClass().getName()
+ ") is not compatible with given class adaptor for type " + classWrapper.adapteeClass().getName()
+ " (this is probably a bug in DBvolution)");
}
this.rowDefinition = rowDefinition;
this.classWrapper = classWrapper;
// pre-cache commonly used things
// (note: if you change this to use lazy-initialisation, you'll have to
// add explicit synchronisation, or it won't be thread-safe anymore)
this.allProperties = new ArrayList();
this.columnProperties = new ArrayList();
for (PropertyWrapperDefinition propertyDefinition : classWrapper.getColumnPropertyDefinitions()) {
final PropertyWrapper propertyWrapper = new PropertyWrapper(this, propertyDefinition, rowDefinition);
addPropertyWrapperToCollection(columnProperties, propertyWrapper);
// this.columnProperties.add(propertyWrapper);
// this.allProperties.add(propertyWrapper);
// if (propertyWrapper.isAutoFilling()){
// autoFillingProperties.add(propertyWrapper);
// }
}
this.autoFillingProperties = new ArrayList();
for (PropertyWrapperDefinition propertyDefinition : classWrapper.getAutoFillingPropertyDefinitions()) {
final PropertyWrapper propertyWrapper = new PropertyWrapper(this, propertyDefinition, rowDefinition);
addPropertyWrapperToCollection(autoFillingProperties, propertyWrapper);
}
this.foreignKeyProperties = new ArrayList();
for (PropertyWrapperDefinition propertyDefinition : classWrapper.getForeignKeyPropertyDefinitions()) {
this.foreignKeyProperties.add(new PropertyWrapper(this, propertyDefinition, rowDefinition));
}
this.primaryKeyProperties = new ArrayList();
for (PropertyWrapperDefinition propertyDefinition : classWrapper.primaryKeyDefinitions()) {
this.primaryKeyProperties.add(new PropertyWrapper(this, propertyDefinition, rowDefinition));
}
}
private void addPropertyWrapperToCollection(List collection, PropertyWrapper propertyWrapper) {
collection.add(propertyWrapper);
this.allProperties.add(propertyWrapper);
}
/**
* Gets a string representation suitable for debugging.
*
* Support DBvolution at
* Patreon
*
* @return a String representing this object sufficient for debugging purposes
*/
@Override
public String toString() {
if (isTable()) {
return getClass().getSimpleName() + "<" + tableName() + ":" + classWrapper.adapteeClass().getName() + ">";
} else {
return getClass().getSimpleName() + "";
}
}
/**
* Two {@code RowDefinitionInstanceWrappers} are equal if they wrap two
* {@code RowDefinition} instances that are themselves equal, and are
* instances of the same class.
*
* @param obj the other object to compare to.
* Support DBvolution at
* Patreon
* @return {@code true} if the two objects are equal, {@code false} otherwise.
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof RowDefinitionInstanceWrapper)) {
return false;
}
RowDefinitionInstanceWrapper other = (RowDefinitionInstanceWrapper) obj;
if (classWrapper == null) {
if (other.classWrapper != null) {
return false;
}
} else if (!classWrapper.equals(other.classWrapper)) {
return false;
}
if (rowDefinition == null) {
if (other.rowDefinition != null) {
return false;
}
} else if (!rowDefinition.equals(other.rowDefinition)) {
return false;
}
return true;
}
/**
* Calculates the hash-code based on the hash-code of the wrapped @{code
* RowDefinition} instance and its class.
*
* Support DBvolution at
* Patreon
*
* @return the hash-code
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((classWrapper == null) ? 0 : classWrapper.hashCode());
result = prime * result + ((rowDefinition == null) ? 0 : rowDefinition.hashCode());
return result;
}
/**
* Gets the class-wrapper for the class of wrapped {@code RowDefinition}
*
* Support DBvolution at
* Patreon
*
* @return the class-wrapper
*/
public RowDefinitionClassWrapper getClassWrapper() {
return classWrapper;
}
/**
* Gets the wrapped object type supported by this {@code ObjectAdaptor}. Note:
* this should be the same as the wrapped object's actual type.
*
* Support DBvolution at
* Patreon
*
* @return the class of the wrapped instance
*/
public Class extends RowDefinition> adapteeRowDefinitionClass() {
return classWrapper.adapteeClass();
}
/**
* Gets the {@link RowDefinition} instance wrapped by this
* {@code ObjectAdaptor}.
*
* Support DBvolution at
* Patreon
*
* @return the {@link RowDefinition} (usually a {@link DBRow} or
* {@link DBReport}) for this instance.
*/
public RowDefinition adapteeRowDefinition() {
return rowDefinition;
}
/**
* Gets the simple name of the class being wrapped by this adaptor.
*
* Use {@link #tableName()} for the name of the table mapped to this class.
*
*
Support DBvolution at
* Patreon
*
* @return the simple class name of the wrapped RowDefinition
*/
public String javaName() {
return classWrapper.javaName();
}
/**
* Gets the fully qualified name of the class being wrapped by this adaptor.
*
* Use {@link #tableName()} for the name of the table mapped to this class.
*
*
Support DBvolution at
* Patreon
*
* @return the full class name of the wrapped RowDefinition
*/
public String qualifiedJavaName() {
return classWrapper.qualifiedJavaName();
}
/**
* Indicates whether this class maps to a database table.
*
*
* If the wrapped {@link RowDefinition} is a {@link DBRow} and thus maps
* directly to a table or view, this method returns true. Other
* RowDefinitions, probably {@link DBReport}, will return false.
*
*
Support DBvolution at
* Patreon
*
* @return TRUE if this RowDefinition maps directly to a table or view, FALSE
* otherwise
*/
public boolean isTable() {
return classWrapper.isTable();
}
/**
* Gets the indicated table name. Applies defaulting if the
* {@link DBTableName} annotation is present but doesn't provide an explicit
* table name.
*
*
* If the {@link DBTableName} annotation is missing, this method returns
* {@code null}.
*
*
Support DBvolution at
* Patreon
*
* @return the table name, if specified explicitly or implicitly.
*/
public String tableName() {
return classWrapper.tableName();
}
public String selectQuery() {
return classWrapper.selectQuery();
}
/**
* Gets the property that is the primary key, if one is marked. Note:
* multi-column primary key tables are not yet supported.
*
* Support DBvolution at
* Patreon
*
* @return the primary key property or null if no primary key
*/
public List getPrimaryKeysPropertyWrappers() {
return primaryKeyProperties;
}
/**
* Gets the property associated with the given column.
*
*
* If multiple properties are annotated for the same column, this method will
* return only the first.
*
*
* Only provides access to properties annotated with {@code DBColumn}.
*
*
* Assumes validation is applied elsewhere to prohibit duplication of column
* names.
*
* @param database database
* @param columnName columnName
*
Support DBvolution at
* Patreon
* @return the Java property associated with the column name supplied. Null if
* no such column is found.
*/
public PropertyWrapper getPropertyByColumn(DBDatabase database, String columnName) {
PropertyWrapperDefinition classProperty = classWrapper.getPropertyDefinitionByColumn(database, columnName);
return (classProperty == null) ? null : new PropertyWrapper(this, classProperty, rowDefinition);
}
/**
* Gets the property by its java field name.
*
* Only provides access to properties annotated with {@code DBColumn}.
*
* @param propertyName propertyName
*
Support DBvolution at
* Patreon
* @return property of the wrapped {@link RowDefinition} associated with the
* java field name supplied. Null if no such property is found.
*/
public PropertyWrapper getPropertyByName(String propertyName) {
PropertyWrapperDefinition classProperty = classWrapper.getPropertyDefinitionByName(propertyName);
return (classProperty == null) ? null : new PropertyWrapper(this, classProperty, rowDefinition);
}
/**
* Gets all properties that are annotated with {@code DBColumn}. This method
* is intended for where you need to get/set property values on all properties
* in the class.
*
*
* Note: if you wish to iterate over the properties and only use their
* definitions (ie: meta-information), this method is not efficient. Use
* {@link #getColumnPropertyDefinitions()} instead in that case.
*
*
Support DBvolution at
* Patreon
*
* @return the non-null list of properties, empty if none
*/
public List getColumnPropertyWrappers() {
return columnProperties;
}
/**
* Gets all properties that are NOT annotated with {@code DBColumn}. This
* method is intended for where you need to get/set property values on all
* properties in the class.
*
*
* Note: if you wish to iterate over the properties and only use their
* definitions (ie: meta-information), this method is not efficient. Use
* {@link #getColumnPropertyDefinitions()} instead in that case.
*
*
Support DBvolution at
* Patreon
*
* @return the non-null list of properties, empty if none
*/
public List getAutoFillingPropertyWrappers() {
return autoFillingProperties;
}
/**
* Gets all foreign key properties.
*
* Support DBvolution at
* Patreon
*
* @return non-null list of PropertyWrappers, empty if no foreign key
* properties
*/
public List getForeignKeyPropertyWrappers() {
return foreignKeyProperties;
}
/**
* Gets all foreign key properties as property definitions.
*
* Support DBvolution at
* Patreon
*
* @return a non-null list of PropertyWrapperDefinitions, empty if no foreign
* key properties
*/
public List getForeignKeyPropertyWrapperDefinitions() {
return classWrapper.getForeignKeyPropertyDefinitions();
}
/**
* Gets all property definitions that are annotated with {@code DBColumn}.
* This method is intended for where you need to examine meta-information
* about all properties in a class.
*
* Support DBvolution at
* Patreon
*
* @return a list of PropertyWrapperDefinitions for the PropertyWrappers of
* this RowDefinition
*/
public List getColumnPropertyDefinitions() {
return classWrapper.getColumnPropertyDefinitions();
}
public String schemaName() {
return classWrapper.schemaName();
}
public boolean isRequiredTable() {
return classWrapper.isRequiredTable();
}
}