package com.reflectiondao.strategy;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.reflectiondao.annotation.DatabaseField;
import com.reflectiondao.types.DatabaseType;
/**
* The Class DaoQueryStrategy.
*
* @param <T>
* the generic type
*/
public class DaoQueryStrategy<T> {
/** The name. */
private Class<T> name;
/**
* Instantiates a new dao query strategy.
*
* @param cName
* the c name
*/
public DaoQueryStrategy(Class<T> cName) {
this.name = cName;
}
/**
* Generate create statement using Reflection.
*
* @param t
* the t
* @return the string
*/
public String generateCreateStatement(T t) {
String name = toDatabaseStyle(this.name.getSimpleName());
List<String> fields = new ArrayList<String>();
DatabaseFieldStrategy<T> strat = new DatabaseFieldStrategy<>();
for (Field f : this.name.getDeclaredFields()) {
DatabaseField db = f.getAnnotation(DatabaseField.class);
if (strat.isNotKey(db)) {
String fieldName = db.name();
fields.add(fieldName);
}
}
String fieldsWithCommas = StringUtils.join(fields.toArray(), ",");
String questionMarks = "";
int i = 0;
for (Field f : this.name.getDeclaredFields()) {
if (i != 0) {
questionMarks += ",";
}
DatabaseField db = f.getAnnotation(DatabaseField.class);
if (strat.isNotKey(db)) {
if (strat.hasDefault(db)) {
questionMarks += db.defaultValue();
} else {
questionMarks += "?";
}
i++;
}
}
String sqlQuery = "insert into " + name + " (" + fieldsWithCommas
+ ") values (" + questionMarks + ")";
System.out.println(sqlQuery);
return sqlQuery;
}
/**
* Creates the select statement.
*
* @return the string
*/
public String createSelectStatement() {
String name = toDatabaseStyle(this.name.getSimpleName());
String primaryKeyName = "";
DatabaseFieldStrategy<T> strat = new DatabaseFieldStrategy<>();
for (Field f : this.name.getDeclaredFields()) {
DatabaseField db = f.getAnnotation(DatabaseField.class);
if (strat.isKey(db)) {
primaryKeyName = db.name();
}
}
return "select * from " + name + " where " + primaryKeyName + "=?";
}
/**
* Gets the primary key value.
*
* @param t
* the t
* @return the primary key value
*/
public Object getPrimaryKeyValue(T t) {
Object a = null;
DatabaseFieldStrategy<T> strat = new DatabaseFieldStrategy<>();
for (Field f : t.getClass().getDeclaredFields()) {
DatabaseField db = f.getAnnotation(DatabaseField.class);
if (strat.isKey(db)) {
f.setAccessible(true);
try {
a = f.get(t);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return a;
}
/**
* Creates the delete statement.
*
* @param t
* the t
* @return the string
*/
public String createDeleteStatement(T t) {
String name = toDatabaseStyle(this.name.getSimpleName());
String primaryKeyName = "";
DatabaseFieldStrategy<T> strat = new DatabaseFieldStrategy<>();
for (Field f : this.name.getDeclaredFields()) {
DatabaseField db = f.getAnnotation(DatabaseField.class);
if (strat.isKey(db)) {
primaryKeyName = db.name();
}
}
return "delete from " + name + " where " + primaryKeyName + " = ?";
}
/**
* Creates the select all statement.
*
* @return the string
*/
public String createSelectAllStatement() {
String name = toDatabaseStyle(this.name.getSimpleName());
return "select * from " + name;
}
/**
* Creates the delete all statement.
*
* @return the string
*/
public String createDeleteAllStatement() {
String name = toDatabaseStyle(this.name.getSimpleName());
return "delete from " + name;
}
/**
* Creates the update statement.
*
* @return the string
*/
public String createUpdateStatement() {
String name = toDatabaseStyle(this.name.getSimpleName());
List<String> fields = new ArrayList<String>();
DatabaseFieldStrategy<T> strat = new DatabaseFieldStrategy<>();
for (Field f : this.name.getDeclaredFields()) {
DatabaseField db = f.getAnnotation(DatabaseField.class);
if (strat.isNotKey(db)) {
String fieldName = db.name();
fields.add(fieldName + "=?");
}
}
String fieldsWithCommas = StringUtils.join(fields.toArray());
return "update " + name + " set " + fieldsWithCommas;
}
/**
* Prepare statement.
*
* @param ps
* the ps
* @param t
* the t
*/
public void prepareStatement(PreparedStatement ps, T t) {
int i = 1;
DatabaseFieldStrategy<T> strat = new DatabaseFieldStrategy<>();
for (Field f : t.getClass().getDeclaredFields()) {
DatabaseField db = f.getAnnotation(DatabaseField.class);
if (strat.isNotKey(db) && !strat.hasDefault(db)) {
DatabaseType type = db.type();
f.setAccessible(true);
strat.processFieldForStatement(type, f, t, ps, i);
i++;
}
}
}
/**
* Creates the update object.
*
* @param t
* the t
* @return the object[]
*/
public Object[] createUpdateObject(T t) {
List<Object> objs = new ArrayList<Object>();
DatabaseFieldStrategy<T> strat = new DatabaseFieldStrategy<>();
for (Field f : this.name.getClass().getDeclaredFields()) {
DatabaseField db = f.getAnnotation(DatabaseField.class);
if (strat.isNotKey(db)) {
f.setAccessible(true);
try {
objs.add(f.get(t));
} catch (Exception e) {
e.printStackTrace();
}
}
}
return objs.toArray();
}
/**
* To database style.
*
* @param s
* the s
* @return the string
*/
private String toDatabaseStyle(String s) {
return splitCamelCase(s);
}
/**
* Split camel case.
*
* @param s
* the s
* @return the string
*/
private String splitCamelCase(String s) {
return s.replaceAll(
String.format("%s|%s|%s", "(?<=[A-Z])(?=[A-Z][a-z])",
"(?<=[^A-Z])(?=[A-Z])", "(?<=[A-Za-z])(?=[^A-Za-z])"),
"_").toLowerCase();
}
}