
com.venky.swf.db.model.reflection.ModelReflector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swf-db Show documentation
Show all versions of swf-db Show documentation
Succinct Web Framework - Db
The newest version!
package com.venky.swf.db.model.reflection;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;
import com.venky.cache.Cache;
import com.venky.core.collections.IgnoreCaseList;
import com.venky.core.collections.IgnoreCaseMap;
import com.venky.core.collections.IgnoreCaseSet;
import com.venky.core.collections.SequenceSet;
import com.venky.core.log.SWFLogger;
import com.venky.core.log.TimerStatistics.Timer;
import com.venky.core.string.StringUtil;
import com.venky.core.util.ObjectUtil;
import com.venky.extension.Registry;
import com.venky.reflection.Reflector.MethodMatcher;
import com.venky.swf.db.Database;
import com.venky.swf.db.JdbcTypeHelper;
import com.venky.swf.db.JdbcTypeHelper.TypeRef;
import com.venky.swf.db.annotations.column.ATTRIBUTE_GROUP;
import com.venky.swf.db.annotations.column.COLUMN_DEF;
import com.venky.swf.db.annotations.column.COLUMN_NAME;
import com.venky.swf.db.annotations.column.COLUMN_SIZE;
import com.venky.swf.db.annotations.column.DATA_TYPE;
import com.venky.swf.db.annotations.column.DECIMAL_DIGITS;
import com.venky.swf.db.annotations.column.ENCRYPTED;
import com.venky.swf.db.annotations.column.HOUSEKEEPING;
import com.venky.swf.db.annotations.column.IS_AUTOINCREMENT;
import com.venky.swf.db.annotations.column.IS_NULLABLE;
import com.venky.swf.db.annotations.column.IS_VIRTUAL;
import com.venky.swf.db.annotations.column.PASSWORD;
import com.venky.swf.db.annotations.column.UNIQUE_KEY;
import com.venky.swf.db.annotations.column.defaulting.CLONING_PROTECT;
import com.venky.swf.db.annotations.column.defaulting.StandardDefault;
import com.venky.swf.db.annotations.column.defaulting.StandardDefaulter;
import com.venky.swf.db.annotations.column.indexing.Index;
import com.venky.swf.db.annotations.column.pm.PARTICIPANT;
import com.venky.swf.db.annotations.column.ui.CONTENT_TYPE;
import com.venky.swf.db.annotations.column.ui.HIDDEN;
import com.venky.swf.db.annotations.column.ui.PROTECTION;
import com.venky.swf.db.annotations.column.ui.PROTECTION.Kind;
import com.venky.swf.db.annotations.column.ui.mimes.MimeType;
import com.venky.swf.db.annotations.column.validations.Enumeration;
import com.venky.swf.db.annotations.model.EXPORTABLE;
import com.venky.swf.db.annotations.model.HAS_DESCRIPTION_FIELD;
import com.venky.swf.db.annotations.model.ORDER_BY;
import com.venky.swf.db.jdbc.ConnectionManager;
import com.venky.swf.db.model.Count;
import com.venky.swf.db.model.Model;
import com.venky.swf.db.model.reflection.TableReflector.MReflector;
import com.venky.swf.db.model.reflection.uniquekey.UniqueKey;
import com.venky.swf.db.model.reflection.uniquekey.UniqueKeyFieldDescriptor;
import com.venky.swf.db.table.Record;
import com.venky.swf.db.table.Table.ColumnDescriptor;
import com.venky.swf.routing.Config;
import com.venky.swf.sql.Conjunction;
import com.venky.swf.sql.Expression;
import com.venky.swf.sql.Operator;
import com.venky.swf.sql.Select;
import com.venky.swf.util.WordWrapUtil;
public class ModelReflector {
@SuppressWarnings("rawtypes")
private static final Map , ModelReflector> modelReflectorByModelClass = new HashMap, ModelReflector>();
@SuppressWarnings("unchecked")
public static ModelReflector instance(Class modelClass){
ModelReflector ref = modelReflectorByModelClass.get(modelClass);
if (ref == null){
synchronized (modelReflectorByModelClass) {
ref = modelReflectorByModelClass.get(modelClass);
if (ref == null){
ref = new ModelReflector(modelClass, TableReflector.instance(modelClass)) ;
modelReflectorByModelClass.put(modelClass, ref);
}
}
}
return ref;
}
private Cache> extensionPointsCache = new Cache>(0,0) {
/**
*
*/
private static final long serialVersionUID = 3938846263913578958L;
@Override
protected SequenceSet getValue(String k) {
StringTokenizer tok = new StringTokenizer(k, "@");
String prefix = tok.nextToken();
String suffix = tok.nextToken();
SequenceSet extnPoints = new SequenceSet();
for (Class extends Model> inHierarchy : getClassHierarchies()){
String extnPoint = prefix + "."+ inHierarchy.getSimpleName() + "." + suffix;
if (Registry.instance().hasExtensions(extnPoint)){
extnPoints.add(extnPoint);
}
}
return extnPoints;
}
};
/**
* Find extension points of the form prefix.modelClass.getSimpleName().suffix for all relevant models in the right sequence.
* @param prefix
* @param suffix
* @return
*/
public List getExtensionPoints(String prefix,String suffix){
return extensionPointsCache.get(prefix+"@"+suffix);
}
private Class modelClass ;
private TableReflector reflector ;
private ModelReflector(Class modelClass,TableReflector reflector){
this.modelClass = modelClass;
this.reflector = reflector;
this.cat = Config.instance().getLogger(modelClass.getName());
}
private ModelReflector() {
}
public Class getModelClass(){
return modelClass;
}
public String getTableName() {
return reflector.getTableName();
}
public Class extends Model> getRealModelClass(){
return TableReflector.getRealModelClass(getModelClass());
}
public SequenceSet> getModelClasses(){
return reflector.getModelClasses();
}
public boolean reflects(Class extends Model> referredModelClass) {
return reflector.reflects(referredModelClass);
}
public boolean canReflect(Object o) {
return reflector.canReflect(o);
}
public String getDescriptionField(){
HAS_DESCRIPTION_FIELD descColumn = getAnnotation(HAS_DESCRIPTION_FIELD.class);
if (descColumn != null){
String column = descColumn.value();
if (getFields().contains(column)){
return column;
}
}
if (getFields().contains("NAME")){
return "NAME";
}
return "ID";
}
@SuppressWarnings("unchecked")
public T get(Object o, String fieldName){
if (o == null){
return null;
}
Model record = null;
Record rawRecord = null ;
if (Record.class.isInstance(o)){
rawRecord = (Record)o;
}else if (Proxy.isProxyClass(o.getClass()) && (o instanceof Model)){
record = (Model)o;
}else {
throw new RuntimeException ("Don't know how to get " + fieldName );
}
if (rawRecord == null){
rawRecord = record.getRawRecord();
}
if (record == null){
record = rawRecord.getAsProxy(getModelClass());
}
Timer timer = cat.startTimer();
try {
T ret = (T)rawRecord.get(fieldName);
if (ret == null){
ColumnDescriptor cd = getColumnDescriptor(fieldName);
if (!cd.isVirtual()){
ret = (T)rawRecord.get(cd.getName());
}
}
Method getter = getFieldGetter(fieldName);
IS_VIRTUAL isVirtual = getAnnotation(getter,IS_VIRTUAL.class);
if (isVirtual != null && isVirtual.value()){
if (ret == null){
ret = (T)getter.invoke(record);
}
}else if (getter.getReturnType().isPrimitive()) {
if (ret == null) {
ret = (T) getJdbcTypeHelper().getTypeRef(getter.getReturnType()).getTypeConverter().valueOf(null);
}
}else if( ret != null && !(getter.getReturnType().isAssignableFrom(ret.getClass()))){
ret = (T)getter.invoke(record);
}
return ret;
} catch (Exception e1) {
throw new RuntimeException(e1);
} finally {
timer.stop();
}
}
public void set(Model record, String fieldName, Object value){
Timer timer = cat.startTimer();
try {
Method getter = getFieldGetter(fieldName);
Method setter = getFieldSetter(fieldName);
TypeRef> typeRef = Database.getJdbcTypeHelper(getPool()).getTypeRef(getter.getReturnType());
if (!ObjectUtil.isVoid(value) || getter.getReturnType().isPrimitive() ){
setter.invoke(record, typeRef.getTypeConverter().valueOf(value));
}else {
setter.invoke(record, getter.getReturnType().cast(null));
}
} catch (Exception e1) {
throw new RuntimeException(fieldName +":" + value , e1);
} finally {
timer.stop();
}
}
public void loadMethods(List into, MethodMatcher matcher) {
Timer timer = cat.startTimer();
try {
reflector.loadMethods(getModelClass(), into, matcher);
}finally{
timer.stop();
}
}
private SequenceSet fieldGetters = null;
public List getFieldGetters(){
if (fieldGetters == null){
synchronized (this) {
if (fieldGetters == null){
SequenceSet fieldGetters = new SequenceSet();
loadMethods(fieldGetters, getFieldGetterMatcher());
this.fieldGetters = fieldGetters;
}
}
}
return fieldGetters;
}
private SequenceSet fieldGetterSignatures = null;
public List getFieldGetterSignatures(){
if (fieldGetterSignatures == null){
synchronized (this) {
if (fieldGetterSignatures == null ){
SequenceSet fieldGetterSignatures = new SequenceSet();
for (Method m : getFieldGetters()){
fieldGetterSignatures.add(getSignature(m));
}
this.fieldGetterSignatures = fieldGetterSignatures;
}
}
}
return fieldGetterSignatures;
}
private SequenceSet fieldSetterSignatures = null;
public List getFieldSetterSignatures(){
if (fieldSetterSignatures == null){
synchronized (this) {
if (fieldSetterSignatures == null ){
SequenceSet fieldSetterSignatures = new SequenceSet();
for (Method m : getFieldSetters()){
fieldSetterSignatures.add(getSignature(m));
}
this.fieldSetterSignatures = fieldSetterSignatures;
}
}
}
return fieldSetterSignatures;
}
private SequenceSet indexedFieldGetters = null;
public List getIndexedFieldGetters(){
if (indexedFieldGetters == null) {
synchronized (this) {
if (indexedFieldGetters == null){
SequenceSet indexedFieldGetters = new SequenceSet();
loadMethods(indexedFieldGetters, getIndexedFieldGetterMatcher());
this.indexedFieldGetters = indexedFieldGetters;
}
}
}
return indexedFieldGetters;
}
private SequenceSet groupedFieldGetters = null ;
public List getGroupedFieldGetters(){
if (groupedFieldGetters == null) {
synchronized (this) {
if (groupedFieldGetters == null){
SequenceSet groupedFieldGetters = new SequenceSet();
loadMethods(groupedFieldGetters, getGroupedFieldGetterMatcher());
this.groupedFieldGetters = groupedFieldGetters;
}
}
}
return groupedFieldGetters;
}
private SequenceSet fieldSetters = null;
public List getFieldSetters(){
if (fieldSetters == null) {
synchronized (this) {
if (fieldSetters == null) {
SequenceSet fieldSetters = new SequenceSet() ;
loadMethods(fieldSetters, getFieldSetterMatcher());
this.fieldSetters = fieldSetters;
}
}
}
return fieldSetters;
}
private SequenceSet referredModelGetters = null;
public List getReferredModelGetters(){
if (referredModelGetters == null ){
synchronized (this) {
if (referredModelGetters == null) {
SequenceSet referredModelGetters = new SequenceSet();
loadMethods(referredModelGetters, getReferredModelGetterMatcher());
this.referredModelGetters = referredModelGetters;
}
}
}
return referredModelGetters;
}
private SequenceSet participantModelGetters = null ;
public List getParticipantModelGetters(){
if (participantModelGetters == null){
synchronized (this) {
if (participantModelGetters == null){
SequenceSet participantModelGetters = new SequenceSet();
loadMethods(participantModelGetters, getParticipantModelGetterMatcher());
this.participantModelGetters = participantModelGetters;
}
}
}
return participantModelGetters;
}
private SequenceSet childModelGetters = null ;
public List getChildGetters(){
if (childModelGetters == null){
synchronized (this) {
if (childModelGetters == null) {
SequenceSet childModelGetters = new SequenceSet();
loadMethods(childModelGetters,getChildrenGetterMatcher());
this.childModelGetters = childModelGetters;
}
}
}
return childModelGetters;
}
public List> getChildModels(){
return getChildModels(false,false);
}
public List> getChildModels(boolean onlyMultipleChildren ,boolean onlyVisible){
SequenceSet> childModels = new SequenceSet>();
for (Method childGetter: getChildGetters()){
if (onlyMultipleChildren && !List.class.isAssignableFrom(childGetter.getReturnType())){
continue;
}
HIDDEN hidden = getAnnotation(childGetter, HIDDEN.class);
if (onlyVisible && hidden != null && hidden.value()){
continue;
}
Class extends Model> childModelClass = getChildModelClass(childGetter);
childModels.add(childModelClass);
}
return childModels;
}
private List allfields = null;
private Map> columnFields = new IgnoreCaseMap>();
private Map fieldColumn = new IgnoreCaseMap();
private void loadAllFields(){
Timer timer = cat.startTimer();
try {
if (allfields != null){
return;
}
synchronized (this) {
if (allfields != null){
return;
}
List fieldGetters = getFieldGetters();
List allfields = new IgnoreCaseList(false);
for (Method fieldGetter : fieldGetters){
String fieldName = getFieldName(fieldGetter);
Map,Annotation> map = getAnnotationMap(fieldGetter);
COLUMN_NAME name = (COLUMN_NAME)map.get(COLUMN_NAME.class);
String columnName = ( name == null ? fieldName : name.value());
allfields.add(fieldName);
List fields = columnFields.get(columnName);
if (fields == null){
fields = new IgnoreCaseList(false);
columnFields.put(columnName, fields);
}
fields.add(fieldName);
fieldColumn.put(fieldName, columnName);
}
this.allfields=allfields;
}
}finally {
timer.stop();
}
}
public List getFields(){
Timer timer = cat.startTimer();
try {
loadAllFields();
return new IgnoreCaseList(false,allfields);
}finally{
timer.stop();
}
}
private Map> groupedFields = null;
public Map> getGroupedFields(){
if (groupedFields == null){
synchronized (this) {
if (groupedFields == null){
Cache> groupedFields = new Cache>() {
@Override
protected List getValue(String groupName) {
return new ArrayList<>();
}
};
for (Method groupedFieldGetter : getGroupedFieldGetters()){
ATTRIBUTE_GROUP attributeGroup = getAnnotation(groupedFieldGetter,ATTRIBUTE_GROUP.class);
groupedFields.get(attributeGroup.value()).add(getFieldName(groupedFieldGetter));
}
this.groupedFields = groupedFields;
}
}
}
return groupedFields;
}
public List getVisibleFields(){
return getVisibleFields(Arrays.asList("ID","LOCK_ID","CREATED_AT" ,"UPDATED_AT"));
}
public List getVisibleFields(List additionalFields){
List fields = getFields();
Set additionalFieldSet = new HashSet<>(additionalFields == null ? new ArrayList<>() : additionalFields);
fields.removeIf( f->(isFieldHidden(f) || isHouseKeepingField(f))&& !additionalFieldSet.contains(f));
return fields;
}
public Map,List>> getChildrenToBeConsidered(Map, List> templateFields){
final Map,List>> childrenToBeConsidered = new Cache,List>>(0,0){
@Override
protected List> getValue(Class extends Model> aClass) {
return new SequenceSet<>();
}
};
if (templateFields == null){
return childrenToBeConsidered;
}
Set templateModelNames = new HashSet<>(templateFields.keySet().stream().map(tm->tm.getSimpleName()).collect(Collectors.toSet()));
if (!templateModelNames.contains(getModelClass().getSimpleName())){
templateModelNames.add(getModelClass().getSimpleName());
}
Stack> models = new Stack<>();
models.push(getModelClass());
Set modelNamesProcessed = new HashSet<>();
while (!models.isEmpty()){
Class extends Model> aChildModel = models.pop();
if (modelNamesProcessed.add(aChildModel.getSimpleName())){
if (templateModelNames.contains(aChildModel.getSimpleName())){
List> grandChildren = ModelReflector.instance(aChildModel).getChildModels();
grandChildren.forEach(aGrandChild->{
if (templateModelNames.contains(aGrandChild.getSimpleName())){
//A First level child included in templates.
childrenToBeConsidered.get(aChildModel).add(aGrandChild);
}
});
models.addAll(grandChildren);
}
}
}
return childrenToBeConsidered;
}
private SequenceSet indexedColumns = null;
public List getIndexedColumns(){
if (indexedColumns == null){
synchronized (this) {
if (indexedColumns == null) {
SequenceSet indexedColumns = new SequenceSet();
for (Method indexedFieldGetter : getIndexedFieldGetters()){
String indexColumnName = getColumnDescriptor(getFieldName(indexedFieldGetter)).getName();
indexedColumns.add(indexColumnName);
}
this.indexedColumns = indexedColumns;
}
}
}
return indexedColumns;
}
private SequenceSet indexedFields = null ;
public SequenceSet getIndexedFields(){
if (indexedFields == null){
synchronized (this) {
if (indexedFields == null){
SequenceSet indexedFields = new SequenceSet();
for (Method indexedFieldGetter : getIndexedFieldGetters()){
indexedFields.add(getFieldName(indexedFieldGetter));
}
this.indexedFields = indexedFields;
}
}
}
return indexedFields;
}
private Cache> uniqueKeys = null;
public Collection> getUniqueKeys(){
if (uniqueKeys == null){
synchronized (this) {
if (uniqueKeys == null){
Cache> uniqueKeys = new Cache>(0,0) {
private static final long serialVersionUID = 1892299842617679145L;
@Override
protected UniqueKey getValue(String keyName) {
return new UniqueKey(getModelClass(), keyName);
}
};
for (Method fieldGetter : getFieldGetters()){
UNIQUE_KEY key = this.getAnnotation(fieldGetter, UNIQUE_KEY.class);
if (key != null){
String fieldName = getFieldName(fieldGetter);
StringTokenizer keys = new StringTokenizer(key.value(),",");
while (keys.hasMoreTokens()){
String keyName = keys.nextToken();
UniqueKey uk = uniqueKeys.get(keyName);
uk.addField(fieldName,key.exportable(),key.allowMultipleRecordsWithNull());
}
}
}
this.uniqueKeys = uniqueKeys;
}
}
}
return uniqueKeys.values();
}
public boolean isDirty(T recordOrProxy,String fieldName) {
Model record = null;
Record rawRecord = null ;
if (Record.class.isInstance(recordOrProxy)){
rawRecord = (Record)recordOrProxy;
}else if (Proxy.isProxyClass(recordOrProxy.getClass()) && (recordOrProxy instanceof Model)){
record = (Model)recordOrProxy;
}else {
throw new RuntimeException ("Don't know how to get " + fieldName );
}
if (rawRecord == null){
rawRecord = record.getRawRecord();
}
return rawRecord.isFieldDirty(fieldName);
}
public Collection getUniqueKeyConditions(T recordOrProxy){
return getUniqueKeyConditions(recordOrProxy, false);
}
public Collection getUniqueKeyConditions(T recordOrProxy,boolean onlyIfContainsDirtyFields){
List col = new ArrayList();
for (UniqueKey key : getUniqueKeys() ){
Expression where = new Expression(getPool(),Conjunction.AND);
boolean ignoreWhereClause = false;
boolean ret = false;
for (UniqueKeyFieldDescriptor fd: key.getFields()){
String fieldName = fd.getFieldName();
ret = ret || !onlyIfContainsDirtyFields || isDirty(recordOrProxy,fieldName);
Object value = get(recordOrProxy, fieldName);
if (value != null){
where.add(new Expression(getPool(),getColumnDescriptor(fd.getFieldName()).getName(),Operator.EQ, value));
}else {
if (!fd.isMultipleRecordsWithNullAllowed()){
where.add(new Expression(getPool(),getColumnDescriptor(fd.getFieldName()).getName(),Operator.EQ));
}else {
ignoreWhereClause = true;
break;
}
}
}
if (!ignoreWhereClause && ret){
col.add(where);
}
}
return col;
}
public List getUniqueFields(){
return getUniqueFields(null);
}
public List getUniqueFields(String keyName){
SequenceSet uniqueFields = new SequenceSet();
for (UniqueKey key : getUniqueKeys()) {
if (keyName == null || key.getKeyName().equalsIgnoreCase(keyName)){
for (UniqueKeyFieldDescriptor fd: key.getFields()){
uniqueFields.add(fd.getFieldName());
}
if (keyName != null) {
break;
}
}
}
return uniqueFields;
}
private List> singleColumnUniqueKeys = null;
public Collection> getSingleColumnUniqueKeys(){
if (singleColumnUniqueKeys == null){
synchronized (this) {
if (singleColumnUniqueKeys == null){
ArrayList> singleColumnUniqueKeys = new ArrayList>();
for (UniqueKey key: getUniqueKeys()){
if (key.size() == 1){
singleColumnUniqueKeys.add(key);
}
}
this.singleColumnUniqueKeys = singleColumnUniqueKeys;
}
}
}
return singleColumnUniqueKeys;
}
private List editableFields = null;
public List getEditableFields(){
if (editableFields == null){
synchronized (this) {
SequenceSet editableFields = new SequenceSet();
for (String field:getFields()){
if (isFieldEditable(field)){
editableFields.add(field);
}
}
this.editableFields = editableFields;
}
}
return editableFields;
}
public List getRealFields(){
return getFields(new RealFieldMatcher());
}
public List getVirtualFields(){
return getFields(new VirtualFieldMatcher());
}
public List getFields(FieldMatcher matcher){
loadAllFields();
List fields = new IgnoreCaseList(false);
for (String field: allfields){
if (matcher == null || matcher.matches(getColumnDescriptor(field))){
fields.add(field);
}
}
return fields;
}
public List getRealColumns(){
return getColumns(new RealFieldMatcher());
}
public List getColumns(FieldMatcher matcher){
Timer timer = cat.startTimer();
try {
List fields = getFields(matcher);
List columns = new IgnoreCaseList(false);
for (String field:fields){
columns.add(getColumnDescriptor(field).getName());
}
return columns;
}finally{
timer.stop();
}
}
public boolean isFieldExportable(String fieldName){
Method fieldGetter = getFieldGetter(fieldName);
EXPORTABLE exportable = getAnnotation(fieldGetter,EXPORTABLE.class);
if (exportable != null && !exportable.value()){
return false;
}
if (isHouseKeepingField(fieldName)){
if (getUniqueKeys().size() > 0 || !"ID".equals(fieldName)){
return false;
}
}
return true;
}
public boolean isFieldCopiedWhileCloning(String fieldName){
Method fieldGetter = getFieldGetter(fieldName);
CLONING_PROTECT cloningProtect = getAnnotation(fieldGetter, CLONING_PROTECT.class);
boolean protectedFromCloning = false;
if (cloningProtect == null){
protectedFromCloning = isHouseKeepingField(fieldName);
}else {
protectedFromCloning = cloningProtect.value();
}
return !protectedFromCloning;
}
public boolean isFieldMandatory(String fieldName){
return !getColumnDescriptor(fieldName).isNullable();
}
public boolean isFieldEditable(String fieldName){
return isFieldVisible(fieldName) && isFieldSettable(fieldName) && !isFieldProtected(fieldName) ;
}
public boolean isFieldSettable(String fieldName){
loadFieldSetters();
return fieldSetterMap.containsKey(fieldName);
}
public boolean isFieldGettable(String fieldName){
loadFieldGetters();
return fieldGetterMap.containsKey(fieldName);
}
public boolean isFieldVisible(String fieldName) {
return !isFieldHidden(fieldName);
}
public boolean isFieldHidden(String fieldName){
Method getter = getFieldGetter(fieldName);
HIDDEN hidden = getAnnotation(getter,HIDDEN.class);
boolean isHidden = (hidden == null ? false : hidden.value());
if (!isHidden){
boolean hideHouseKeepingFields = (Boolean) Database.getJdbcTypeHelper(getPool()).getTypeRef(Boolean.class).getTypeConverter().valueOf(Config.instance().getProperty("swf.hide.housekeeping.fields","N"));
isHidden = hideHouseKeepingFields && isHouseKeepingField(fieldName);
}
return isHidden;
}
public String getFieldName(final String columnOrFieldName){
Timer timer = cat.startTimer();
try {
loadAllFields();
//Mostly column name and fieldnames are same.
if (!fieldColumn.containsKey(columnOrFieldName)){
List fields = columnFields.get(columnOrFieldName);
int numFields = fields == null ? 0 : fields.size();
if (numFields == 1){
return fields.get(0);
}else if (numFields == 0){
cat.finest("Field not found for Column " + columnOrFieldName + " in " + getTableName() + ", Model Is " + getModelClass().getName());
return null;
}
}
return columnOrFieldName;
}finally{
timer.stop();
}
}
private SWFLogger cat = null;
public boolean isHouseKeepingField(String fieldName){
Method getter = getFieldGetter(fieldName);
return isAnnotationPresent(getter,HOUSEKEEPING.class);
}
public boolean isFieldPassword(String fieldName){
Method getter = getFieldGetter(fieldName);
return isAnnotationPresent(getter,PASSWORD.class);
}
public boolean isFieldEncrypted(String fieldName){
return getEncryptedFields().contains(fieldName);
}
List encryptedFields = null;
public List getEncryptedFields(){
if (encryptedFields == null){
synchronized (this) {
if (this.encryptedFields == null){
this.encryptedFields = getFields(new EncryptedFieldMatcher());
}
}
}
return new IgnoreCaseList(false,encryptedFields);
}
/**
* Internal method. Not to use it by normal developers. !!! WARNING!
* @param encryptedFields
*/
public void setEncryptedFields(List encryptedFields){
this.encryptedFields = encryptedFields;
}
public boolean isFieldProtected(String fieldName){
return (getFieldProtection(fieldName) != Kind.EDITABLE);
}
public boolean isFieldDisabled(String fieldName){
return (getFieldProtection(fieldName) == Kind.DISABLED || !isFieldSettable(fieldName));
}
public Kind getFieldProtection(String fieldName){
Method getter = getFieldGetter(fieldName);
PROTECTION p = getAnnotation(getter,PROTECTION.class);
return p == null ? Kind.EDITABLE : p.value();
}
public boolean isFieldVirtual(String fieldName){
Method getter = getFieldGetter(fieldName);
IS_VIRTUAL p = getAnnotation(getter,IS_VIRTUAL.class);
return (p == null ? false : p.value());
}
public boolean isFieldEnumeration(String fieldName){
Method getter = getFieldGetter(fieldName);
return isAnnotationPresent(getter,Enumeration.class);
}
public boolean isVirtual(){
IS_VIRTUAL isVirtual = getAnnotation(IS_VIRTUAL.class);
if (isVirtual != null && isVirtual.value()) {
return true;
}
return false;
}
public String getPool(){
return reflector.getPool();
}
public JdbcTypeHelper getJdbcTypeHelper() {
return Database.getJdbcTypeHelper(getPool());
}
public boolean isVoid(Object o) {
return getJdbcTypeHelper().isVoid(o);
}
TimeZone zone = null;
public TimeZone getTimeZone(){
if (zone == null) {
synchronized (this) {
if (zone == null){
String zoneId = Config.instance().getProperty(ConnectionManager.instance().getNormalizedPropertyName("swf.jdbc."+getPool()+".timezone"));
if (ObjectUtil.isVoid(zoneId)){
zone = TimeZone.getDefault();
}else {
zone = TimeZone.getTimeZone(zoneId);
if (!StringUtil.equals(zone.getID(),zoneId)){
throw new RuntimeException("Invalid timezone specified for pool " +getPool());
}
}
}
}
}
return zone;
}
public Timestamp getNow(){
return StandardDefaulter.getNow(getTimeZone());
}
public int getMaxDataLength(String fieldName){
ColumnDescriptor fieldDescriptor = getColumnDescriptor(fieldName);
String fieldColumnName = fieldDescriptor.getName();
int size = fieldDescriptor.getSize();
Class> javaClass = getFieldGetter(fieldName).getReturnType();
if (String.class.isAssignableFrom(javaClass)){
List counts = new ArrayList();
if (size == 0 && !isVirtual() && !fieldDescriptor.isVirtual() && Config.instance().getBooleanProperty(modelClass.getSimpleName()+ "."+fieldColumnName+ ".checkMaxLength")){
counts = new Select("MAX(LENGTH("+ fieldColumnName + ")) AS COUNT").from(modelClass).execute(Count.class);
if (!counts.isEmpty()){
size = (int) counts.get(0).getCount();
}else {
size = MAX_DATA_LENGTH_FOR_TEXT_BOX;
}
}else {
size = size == 0 ? MAX_DATA_LENGTH_FOR_TEXT_BOX : size;
}
}else if (Reader.class.isAssignableFrom(javaClass)){
size = MAX_DATA_LENGTH_FOR_TEXT_BOX + 1;
}
return size;
}
public boolean isFieldDisplayLongForTextBox(String fieldName){
if (isFieldValueALongText(fieldName)){
return true;
}else {
Method getter = getFieldGetter(fieldName);
Method referredModelGetter = getReferredModelGetterFor(getter);
if (referredModelGetter != null){
Class extends Model> referredModelClass = getReferredModelClass(referredModelGetter);
ModelReflector extends Model> referredModelReflector = ModelReflector.instance(referredModelClass);
if (referredModelReflector != this || !ObjectUtil.equals(fieldName,referredModelReflector.getDescriptionField())){
return referredModelReflector.isFieldValueALongText(referredModelReflector.getDescriptionField());
}
}
return false;
}
}
public static final int MAX_DATA_LENGTH_FOR_TEXT_BOX = 80 ;
public boolean isFieldValueALongText(String fieldName){
return isFieldValueALongText(fieldName,null);
}
public boolean isFieldValueALongText(String fieldName,Object fieldValue){
Method getter = getFieldGetter(fieldName);
COLUMN_SIZE columnSizeSpecified = getAnnotation(getter,COLUMN_SIZE.class);
Class> returnType = getter.getReturnType();
if (Reader.class.isAssignableFrom(returnType) ||
(columnSizeSpecified != null && (String.class.isAssignableFrom(returnType)))){
int len = 0;
if (!isFieldEditable(fieldName) && String.class.isAssignableFrom(returnType)){
len = WordWrapUtil.getNumRowsRequired(StringUtil.valueOf(fieldValue),columnSizeSpecified.value()) * MAX_DATA_LENGTH_FOR_TEXT_BOX;
}else {
len = getMaxDataLength(fieldName);
}
return (len > MAX_DATA_LENGTH_FOR_TEXT_BOX) ;
}
return false;
}
private Cache fieldNameCache = new Cache(0,0) {
/**
*
*/
private static final long serialVersionUID = 4626497380273214264L;
@Override
protected String getValue(Method method) {
String fieldName = null;
if (getFieldGetterMatcher().matches(method) ){
for (String getterPrefix:getterPrefixes){
if (method.getName().startsWith(getterPrefix)){
fieldName = StringUtil.underscorize(method.getName().substring(getterPrefix.length()));
break;
}
}
}else if(getFieldSetterMatcher().matches(method)){
fieldName = StringUtil.underscorize(method.getName().substring(3));
}
return fieldName;
}
};
public String getFieldName(Method method){
Timer timer = cat.startTimer();
try {
return fieldNameCache.get(method);
}finally{
timer.stop();
}
}
public String getContentType(Model record, String fieldName){
String mimeType = null ;
List fields = getFields();
if (fields.contains(fieldName)){
Method getter = getFieldGetter(fieldName);
if (InputStream.class.isAssignableFrom(getter.getReturnType())){
CONTENT_TYPE ct = getAnnotation(getter,CONTENT_TYPE.class);
if (ct != null){
mimeType = ct.value().toString();
}else {
String contentTypeFieldName = fieldName + "_CONTENT_TYPE";
if (getFields().contains(contentTypeFieldName)){
mimeType = get(record,contentTypeFieldName);
}
}
}
}
if (mimeType == null){
mimeType = getDefaultContentType();
}
return mimeType;
}
public String getDefaultContentType(){
return MimeType.APPLICATION_OCTET_STREAM.toString();
}
public String getContentName(Model record, String fieldName){
List fields = getFields();
if (fields.contains(fieldName)){
Method getter = getFieldGetter(fieldName);
if (InputStream.class.isAssignableFrom(getter.getReturnType())){
String fileName = fieldName + "_CONTENT_NAME";
if (fields.contains(fileName)){
return get(record,fileName);
}
}
}
return null;
}
public int getContentSize(Model record, String fieldName){
List fields = getFields();
if (fields.contains(fieldName)){
Method getter = getFieldGetter(fieldName);
if (InputStream.class.isAssignableFrom(getter.getReturnType())){
String sizeFieldName = fieldName + "_CONTENT_SIZE";
if (fields.contains(sizeFieldName)){
Integer i = get(record,sizeFieldName);
return i;
}else {
InputStream is = get(record,fieldName);
try {
if (is != null){
return is.available();
}else {
return 0;
}
} catch (IOException e) {
//
}
}
}
}
return -1;
}
private static final String[] getterPrefixes = new String[]{"get" , "is"};
private Map fieldGetterMap = null ;
public void loadFieldGetters(){
if (fieldGetterMap == null){
synchronized (this) {
if (fieldGetterMap == null) {
IgnoreCaseMap fieldGetterMap = new IgnoreCaseMap();
List fieldGetters = getFieldGetters();
for (Method fieldGetter: fieldGetters){
fieldGetterMap.put(getFieldName(fieldGetter), fieldGetter);
}
this.fieldGetterMap = fieldGetterMap;
}
}
}
}
public Method getFieldGetter(String fieldName){
Timer timer = cat.startTimer();
try {
loadFieldGetters();
Method getter = fieldGetterMap.get(fieldName);
if (getter == null){
String getterName = "get/is" + StringUtil.camelize(fieldName);
throw new FieldGetterMissingException("Method " + getterName + "() with appropriate return type is missing");
}
return getter;
}finally{
timer.stop();
}
}
private Map fieldSetterMap = null;
private void loadFieldSetters(){
if (fieldSetterMap == null){
synchronized (this) {
if (fieldSetterMap == null){
IgnoreCaseMap fieldSetterMap = new IgnoreCaseMap();
List fieldSetters = getFieldSetters();
for (Method fieldSetter: fieldSetters){
fieldSetterMap.put(getFieldName(fieldSetter), fieldSetter);
}
this.fieldSetterMap = fieldSetterMap;
}
}
}
}
public Method getFieldSetter(String fieldName){
Timer timer = cat.startTimer();
try {
loadFieldSetters();
Method setter = fieldSetterMap.get(fieldName);
if (setter == null){
Method getter = getFieldGetter(fieldName);
String setterName = "set"+StringUtil.camelize(fieldName) +"(" + getter.getReturnType().getName() + ")";
throw new FieldSetterMissingException("Method: public void " + setterName + " missing!");
}
return setter;
}finally{
timer.stop();
}
}
public static class FieldSetterMissingException extends RuntimeException {
private static final long serialVersionUID = 5976842300991239658L;
public FieldSetterMissingException(String message){
super(message);
}
}
public static class FieldGetterMissingException extends RuntimeException {
private static final long serialVersionUID = 5976842300991239658L;
public FieldGetterMissingException(String message){
super(message);
}
}
public String getSignature(Method method){
return reflector.getSignature(method);
}
private Map, Annotation>> annotationMap = new HashMap,Annotation>>();
private Map, Annotation> getAnnotationMap(Method getter){
Timer timer = cat.startTimer();
try {
String signature = getSignature(getter);
Map, Annotation> map = annotationMap.get(signature);
if (map != null){
return map;
}
synchronized (this) {
map = annotationMap.get(signature);
if (map == null) {
map = new HashMap, Annotation>();
for (Class extends Model> modelClass:reflector.getSiblingModelClasses(getModelClass())){
MReflector extends Model> ref = MReflector.instance(modelClass);
//We could have simple called getAnnotation(getter,Annotation class) but that would mean looping multiple times for
//each annotation needed. hence this optimization.
if (map.get(COLUMN_NAME.class) == null){ map.put(COLUMN_NAME.class,ref.getAnnotation(getter,COLUMN_NAME.class)); }
if (map.get(COLUMN_SIZE.class) == null){ map.put(COLUMN_SIZE.class,ref.getAnnotation(getter,COLUMN_SIZE.class)); }
if (map.get(DATA_TYPE.class ) == null){ map.put(DATA_TYPE.class ,ref.getAnnotation(getter, DATA_TYPE.class)); }
if (map.get(DECIMAL_DIGITS.class) == null){ map.put(DECIMAL_DIGITS.class,ref.getAnnotation(getter,DECIMAL_DIGITS.class)); }
if (map.get(IS_NULLABLE.class) == null){ map.put(IS_NULLABLE.class,ref.getAnnotation(getter,IS_NULLABLE.class)); }
if (map.get(IS_AUTOINCREMENT.class) == null){ map.put(IS_AUTOINCREMENT.class,ref.getAnnotation(getter,IS_AUTOINCREMENT.class)); }
if (map.get(IS_VIRTUAL.class) == null){ map.put(IS_VIRTUAL.class,ref.getAnnotation(getter,IS_VIRTUAL.class)); }
if (map.get(COLUMN_DEF.class) == null){ map.put(COLUMN_DEF.class,ref.getAnnotation(getter,COLUMN_DEF.class)); }
if (map.get(ENCRYPTED.class) == null){ map.put(ENCRYPTED.class,ref.getAnnotation(getter,ENCRYPTED.class)); }
}
annotationMap.put(signature, map);
}
}
return map;
}finally{
timer.stop();
}
}
public ColumnDescriptor getColumnDescriptor(String fieldName){
Timer timer =cat.startTimer(null, Config.instance().isTimerAdditive());
try {
return getColumnDescriptors().get(fieldName);
}finally{
timer.stop();
}
}
/*
public ColumnDescriptor getColumnDescriptor(Method fieldGetter){
Timer timer =cat.startTimer(null, Config.instance().isTimerAdditive());
try {
return getColumnDescriptor(getFieldName(fieldGetter));
}finally{
timer.stop();
}
}*/
public boolean hasMultipleAccess(String columnName){
Timer timer = cat.startTimer();
try {
List fields = columnFields.get(columnName);
return (fields != null && fields.size() > 1);
}finally{
timer.stop();
}
}
private class ColumnDescriptorCache extends Cache{
private static final long serialVersionUID = 302310307824397179L;
public ColumnDescriptorCache(){
super(Cache.MAX_ENTRIES_UNLIMITED,0);
loadAllFields();
}
@Override
protected ColumnDescriptor getValue(String fieldName) {
Timer timer =cat.startTimer(null, Config.instance().isTimerAdditive());
try {
Method fieldGetter = getFieldGetter(fieldName);
if (!getFieldGetters().contains(fieldGetter)){
throw new RuntimeException("Method:" + fieldGetter.getName() + " is not recognizable as a a FieldGetter");
}
//String fieldName = getFieldName(fieldGetter);
String columnName = fieldColumn.get(fieldName);
if (hasMultipleAccess(columnName)){
if (!columnFields.get(columnName).contains(columnName)){
throw new RuntimeException(columnName + " has multiple access while none of the field has the same name!(" + columnFields.get(columnName).toString() + ")");
}else if (!columnName.equalsIgnoreCase(fieldName)){
return get(columnName);
}
}
Map, Annotation> map = getAnnotationMap(fieldGetter);
COLUMN_SIZE size = (COLUMN_SIZE) map.get(COLUMN_SIZE.class);
DATA_TYPE type = (DATA_TYPE) map.get(DATA_TYPE.class);
DECIMAL_DIGITS digits = (DECIMAL_DIGITS) map.get(DECIMAL_DIGITS.class);
IS_NULLABLE isNullable = (IS_NULLABLE)map.get(IS_NULLABLE.class);
IS_AUTOINCREMENT isAutoIncrement = (IS_AUTOINCREMENT)map.get(IS_AUTOINCREMENT.class);
IS_VIRTUAL isVirtual = (IS_VIRTUAL)map.get(IS_VIRTUAL.class);
COLUMN_DEF colDef = (COLUMN_DEF)map.get(COLUMN_DEF.class);
ENCRYPTED encrypted = (ENCRYPTED)map.get(ENCRYPTED.class);
ColumnDescriptor cd = new ColumnDescriptor(getPool());
cd.setName(columnName);
JdbcTypeHelper helper = Database.getJdbcTypeHelper(getPool());
TypeRef> typeRef = helper.getTypeRef(fieldGetter.getReturnType());
assert typeRef != null;
cd.setJDBCType(type == null ? typeRef.getJdbcType() : type.value());
cd.setNullable(isNullable != null ? isNullable.value() : !fieldGetter.getReturnType().isPrimitive());
cd.setSize(size == null? typeRef.getSize() : size.value());
cd.setScale(digits == null ? typeRef.getScale() : digits.value());
cd.setAutoIncrement(isAutoIncrement == null? false : true);
cd.setVirtual(isVirtual == null ? false : isVirtual.value());
cd.setEncrypted(encrypted == null ? false: encrypted.value());
if (colDef != null && colDef.value() != StandardDefault.NONE){
cd.setColumnDefault(toDefaultKW(typeRef,colDef));
}
return cd;
}finally {
timer.stop();
}
}
}
private ColumnDescriptorCache columnDescriptors = null;
private ColumnDescriptorCache getColumnDescriptors(){
if (columnDescriptors == null){
synchronized (this) {
if (columnDescriptors == null) {
columnDescriptors = new ColumnDescriptorCache();
}
}
}
return columnDescriptors;
}
private String toDefaultKW(TypeRef> ref, COLUMN_DEF def){
return Database.getJdbcTypeHelper(getPool()).toDefaultKW(ref,def);
}
public boolean isAnnotationPresent(Class extends Annotation> annotationClass){
return getAnnotation(annotationClass) != null;
}
public boolean isAnnotationPresent(Method method, Class extends Annotation> annotationClass ){
return getAnnotation(method, annotationClass) != null;
}
private Cache,Annotation> classAnnotationCache = new Cache, Annotation>(0,0){
/**
*
*/
private static final long serialVersionUID = -4698644911072168124L;
@Override
protected Annotation getValue(Class extends Annotation> annotationClass) {
Annotation a = reflector.getAnnotation(getModelClass(), annotationClass);
return a;
}
};
@SuppressWarnings("unchecked")
public A getAnnotation(Class annotationClass){
return (A)classAnnotationCache.get(annotationClass);
}
private Cache,Annotation>> methodAnnotationCache = new Cache,Annotation>>(Cache.MAX_ENTRIES_UNLIMITED,0){
/**
*
*/
private static final long serialVersionUID = 4256698883995018084L;
@Override
protected Cache, Annotation> getValue(final Method k) {
Timer timer = cat.startTimer();
try {
return new Cache, Annotation>(0,0) {
/**
*
*/
private static final long serialVersionUID = 4851400562811398820L;
@Override
protected Annotation getValue(
Class extends Annotation> annotationClass) {
Timer timer = cat.startTimer();
try {
return reflector.getAnnotation(getModelClass(),k,
annotationClass);
} finally {
timer.stop();
}
}
};
} finally {
timer.stop();
}
}
};
@SuppressWarnings("unchecked")
public A getAnnotation(Method method, Class annotationClass){
return (A)methodAnnotationCache.get(method).get(annotationClass);
}
public Class extends Model> getChildModelClass(Method method){
Timer timer = cat.startTimer();
try {
Class> possibleChildClass = null;
if (!getClassForests().contains(method.getDeclaringClass())){
return null;
}
if (getGetterMatcher().matches(method)){
Class> retType = method.getReturnType();
if (List.class.isAssignableFrom(retType)){
ParameterizedType parameterizedType = (ParameterizedType)method.getGenericReturnType();
Type type = parameterizedType.getActualTypeArguments()[0];
if (type instanceof Class){
possibleChildClass = (Class>)type;
}else if (type instanceof TypeVariable){
possibleChildClass = (Class>)(((TypeVariable>)type).getBounds()[0]);
}
}
if (possibleChildClass != null && Model.class.isAssignableFrom(possibleChildClass)){
// Validate That child has a parentReferenceId.
@SuppressWarnings("unchecked")
Class extends Model> childClass = (Class extends Model>)possibleChildClass;
ModelReflector extends Model> childReflector = ModelReflector.instance(childClass);
if (!childReflector.getReferenceFields(getModelClass()).isEmpty()){
return childClass;
}
}
}
return null;
}finally{
timer.stop();
}
}
public List getReferenceFields(Class extends Model> referredModelClass){
Timer timer = cat.startTimer();
try {
List names = new ArrayList();
for (Method referredModelGetter : getReferredModelGetters(referredModelClass)){
names.add(getReferenceField(referredModelGetter));
}
return names;
}finally{
timer.stop();
}
}
@SuppressWarnings("unchecked")
public List getReferredModelGetters(final Class extends Model> referredModelClass){
Timer timer = cat.startTimer();
try {
ModelReflector extends Model> referredModelReflector = ModelReflector.instance(referredModelClass);
List referredModelGetters = getReferredModelGetters();
List ret = new ArrayList();
for (Method aReferredModelGetter: referredModelGetters){
if (referredModelReflector.reflects((Class extends Model>)aReferredModelGetter.getReturnType())){
ret.add(aReferredModelGetter);
}
}
return ret;
}finally{
timer.stop();
}
}
@SuppressWarnings("unchecked")
public Class extends Model> getReferredModelClass(Method referredModelGetter) {
Timer timer = cat.startTimer();
try {
if (!getClassForests().contains(referredModelGetter.getDeclaringClass())) {
return null;
}
Class extends Model> referredModelClass = null;
Class> possibleReferredModelClass = referredModelGetter.getReturnType();
if (Model.class.isAssignableFrom(possibleReferredModelClass)
&& getGetterMatcher().matches(referredModelGetter)) {
String referredIdFieldName = getReferenceField(referredModelGetter);
if (getFields().contains(referredIdFieldName)) {
referredModelClass = (Class extends Model>) possibleReferredModelClass;
}
}
return referredModelClass;
} finally {
timer.stop();
}
}
Map referredModelGetterToReferenceFieldMap = new HashMap();
public String getReferenceField(Method parentGetter){
String field = referredModelGetterToReferenceFieldMap.get(parentGetter);
if (field == null && !referredModelGetterToReferenceFieldMap.containsKey(parentGetter)){
field = StringUtil.underscorize(parentGetter.getName().substring(3) + "Id");
referredModelGetterToReferenceFieldMap.put(parentGetter, field);
}
return field;
}
private Map referredModelIdGetterToReferredModelGetterMap = null;
public Method getReferredModelGetterFor(Method referredModelIdGetter) {
if (referredModelIdGetterToReferredModelGetterMap == null){
synchronized (this){
if (referredModelIdGetterToReferredModelGetterMap == null){
Map referredModelIdGetterToReferredModelGetterMap = new HashMap<>();
for (Method refModelGetter : getReferredModelGetters()){
String field = getReferenceField(refModelGetter);
Method refModelIdGetter = getFieldGetter(field);
referredModelIdGetterToReferredModelGetterMap.put(refModelIdGetter,refModelGetter);
}
this.referredModelIdGetterToReferredModelGetterMap = referredModelIdGetterToReferredModelGetterMap;
}
}
}
return referredModelIdGetterToReferredModelGetterMap.get(referredModelIdGetter);
}
private SequenceSet> classHierarchies = null;
public SequenceSet> getClassHierarchies() {
if (classHierarchies == null){
synchronized (this) {
if (classHierarchies == null) {
classHierarchies = reflector.getClassHierarchies(getModelClass());
}
}
}
return classHierarchies;
}
private SequenceSet> classForests = null;
public SequenceSet> getClassForests(){
if (classForests == null){
synchronized (this) {
if (classForests == null){
classForests = reflector.getClassForests(getModelClass());
}
}
}
return classForests;
}
//Field MAtchers
public static interface FieldMatcher {
public boolean matches(ColumnDescriptor cd);
}
private class RealFieldMatcher implements FieldMatcher {
public boolean matches(ColumnDescriptor cd) {
return !cd.isVirtual();
}
}
private class VirtualFieldMatcher implements FieldMatcher {
public boolean matches(ColumnDescriptor cd) {
return cd.isVirtual();
}
}
private class EncryptedFieldMatcher implements FieldMatcher{
public boolean matches(ColumnDescriptor cd) {
return cd.isEncrypted();
}
}
//Method Matcher
private final MethodMatcher getterMatcher = new GetterMatcher();
public MethodMatcher getGetterMatcher(){
return getterMatcher;
}
public class GetterMatcher implements MethodMatcher{
public boolean matches(Method method){
Timer timer = cat.startTimer();
try {
String mName = method.getName();
Class> retType = method.getReturnType();
Class>[] paramTypes = method.getParameterTypes();
if ( ((mName.startsWith("get") && retType != Void.TYPE) ||
mName.startsWith("is") && (boolean.class == retType || Boolean.class == retType) ) &&
(paramTypes == null || paramTypes.length == 0)){
return true;
}
return false;
} finally {
timer.stop();
}
}
}
private final MethodMatcher fieldGetterMatcher = new FieldGetterMatcher();
public MethodMatcher getFieldGetterMatcher() {
return fieldGetterMatcher;
}
private final MethodMatcher indexedFieldGetterMatcher = new IndexedFieldGetterMatcher();
public MethodMatcher getIndexedFieldGetterMatcher() {
return indexedFieldGetterMatcher;
}
private final MethodMatcher groupedFieldGetterMatcher = new GroupedFieldGetterMatcher();
public MethodMatcher getGroupedFieldGetterMatcher() {
return groupedFieldGetterMatcher;
}
public class GroupedFieldGetterMatcher extends FieldGetterMatcher {
@Override
public boolean matches(Method method){
if (method.getName().endsWith("Id")) {
if (getReferredModelGetterFor(method) != null){
return false;
}
}
return super.matches(method) && isAnnotationPresent(method,ATTRIBUTE_GROUP.class) ;
}
}
public class IndexedFieldGetterMatcher extends FieldGetterMatcher {
@Override
public boolean matches(Method method){
return super.matches(method) && isAnnotationPresent(method,Index.class) ;
}
}
public class FieldGetterMatcher extends GetterMatcher{
@Override
public boolean matches(Method method){
Timer timer = cat.startTimer();
try {
if (super.matches(method) && !Modifier.isStatic(method.getModifiers()) &&
!Model.class.isAssignableFrom(method.getReturnType()) &&
Database.getJdbcTypeHelper(getPool()).getTypeRef(method.getReturnType()) != null){
return true;
}
return false;
}finally{
timer.stop();
}
}
}
public class SetterMatcher implements MethodMatcher{
public boolean matches(Method method){
Timer timer = cat.startTimer();
try {
String mName = method.getName();
Class> retType = method.getReturnType();
Class>[] paramTypes = method.getParameterTypes();
if (mName.startsWith("set") && (Void.TYPE == retType) &&
(paramTypes != null && paramTypes.length == 1) ){
return true;
}
return false;
}finally{
timer.stop();
}
}
}
private final MethodMatcher fieldSetterMatcher = new FieldSetterMatcher();
public MethodMatcher getFieldSetterMatcher() {
return fieldSetterMatcher;
}
public class FieldSetterMatcher extends SetterMatcher{
@Override
public boolean matches(Method method){
Timer timer = cat.startTimer();
try {
if (super.matches(method)
&& Database.getJdbcTypeHelper(getPool()).getTypeRef(
method.getParameterTypes()[0]) != null) {
return true;
}
return false;
} finally {
timer.stop();
}
}
}
//RelationShip Methods matchers
private final MethodMatcher referredModelGetterMatcher= new ReferredModelGetterMatcher();
public MethodMatcher getReferredModelGetterMatcher(){
return referredModelGetterMatcher;
}
private class ReferredModelGetterMatcher implements MethodMatcher{
public boolean matches(Method method){
Timer timer = cat.startTimer();
try {
return getReferredModelClass(method) != null;
} finally {
timer.stop();
}
}
}
private final MethodMatcher participantModelGetterMatcher = new ParticipantModelGetterMatcher();
public MethodMatcher getParticipantModelGetterMatcher(){
return participantModelGetterMatcher;
}
private class ParticipantModelGetterMatcher extends ReferredModelGetterMatcher{
public boolean matches(Method method){
Timer timer = cat.startTimer();
try {
if (super.matches(method)){
return isAnnotationPresent(getFieldGetter(getReferenceField(method)), PARTICIPANT.class);
}
return false;
} finally {
timer.stop();
}
}
}
private final MethodMatcher childrenGetterMatcher= new ChildrenGetterMatcher();
public MethodMatcher getChildrenGetterMatcher(){
return childrenGetterMatcher;
}
private class ChildrenGetterMatcher implements MethodMatcher{
public boolean matches(Method method){
return (getChildModelClass(method) != null && !Modifier.isStatic(method.getModifiers()));
}
}
public String getOrderBy(){
ORDER_BY order = getAnnotation(ORDER_BY.class);
String orderBy = ORDER_BY.DEFAULT;
if (order != null){
orderBy = order.value();
}
return orderBy;
}
private Cache participatingRole = new Cache(0,0) {
/**
*
*/
private static final long serialVersionUID = 163426440760440104L;
@Override
protected String getValue(String referencedModelIdFieldName) {
return referencedModelIdFieldName.substring(0, referencedModelIdFieldName.length()-3) ; //Remove "_ID" from the end.
}
};
public String getParticipatingRole(String referencedModelIdFieldName){
return participatingRole.get(referencedModelIdFieldName);
}
private Set participatableRoles = null;
public Set getParticipatableRoles(){
if (participatableRoles == null){
synchronized (this) {
if (participatableRoles == null){
HashSet participatableRoles = new HashSet();
for (Method m : getParticipantModelGetters()){
participatableRoles.add(getParticipatingRole(getReferenceField(m)));
}
this.participatableRoles = participatableRoles;
}
}
}
return new HashSet(participatableRoles);
}
public static void dispose() {
ModelReflector.modelReflectorByModelClass.clear();
}
private Set autoIncrementColumns = null;
public Set getAutoIncrementColumns() {
if (autoIncrementColumns == null){
synchronized (this) {
if (autoIncrementColumns == null){
autoIncrementColumns = new IgnoreCaseSet();
for (String f : getFields()){
ColumnDescriptor d = getColumnDescriptor(f);
if (d.isAutoIncrement()){
autoIncrementColumns.add(d.getName());
}
}
}
}
}
return Collections.unmodifiableSet(autoIncrementColumns);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy