diff --git a/base/src/org/adempiere/util/ModelClassGenerator.java b/base/src/org/adempiere/util/ModelClassGenerator.java
index 77ff3d91e1..f1ddf0cd6d 100644
--- a/base/src/org/adempiere/util/ModelClassGenerator.java
+++ b/base/src/org/adempiere/util/ModelClassGenerator.java
@@ -34,13 +34,10 @@ import java.util.logging.Level;
import org.adempiere.exceptions.DBException;
import org.compiere.Adempiere;
-import org.compiere.model.MEntityType;
-import org.compiere.model.MTable;
import org.compiere.util.CLogMgt;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
-import org.compiere.util.Env;
/**
* Generate Model Classes extending PO.
@@ -53,12 +50,15 @@ import org.compiere.util.Env;
*
BF [ 1781629 ] Don't use Env.NL in model class/interface generators
* FR [ 1781630 ] Generated class/interfaces have a lot of unused imports
* BF [ 1781632 ] Generated class/interfaces should be UTF-8
- * better formating of generated source
- * [ 1787876 ] ModelClassGenerator: list constants should be ordered
+ * FR [ xxxxxxx ] better formating of generated source
+ * FR [ 1787876 ] ModelClassGenerator: list constants should be ordered
* FR [ 1803309 ] Model generator: generate get method for Search cols
* FR [ 1990848 ] Generated Models: remove hardcoded field length
* FR [ 2343096 ] Model Generator: Improve Reference Class Detection
* BF [ 2780468 ] ModelClassGenerator: not generating methods for Created*
+ * --
+ * FR [ 2848449 ] ModelClassGenerator: Implement model getters
+ * https://sourceforge.net/tracker/?func=detail&atid=879335&aid=2848449&group_id=176962
* @author Victor Perez, e-Evolution
* FR [ 1785001 ] Using ModelPackage of EntityType to Generate Model Class
*/
@@ -96,9 +96,6 @@ public class ModelClassGenerator
/** Package Name */
private String packageName = "";
- /** EntityType */
- private static final MEntityType[] entityTypes = MEntityType.getEntityTypes(Env.getCtx());
-
/**
* Add Header info to buffer
@@ -314,7 +311,8 @@ public class ModelClassGenerator
columnName, isUpdateable, isMandatory,
displayType, AD_Reference_Value_ID, fieldLength,
defaultValue, ValueMin, ValueMax, VFormat,
- Callout, Name, Description, virtualColumn, IsEncrypted, IsKey)
+ Callout, Name, Description, virtualColumn, IsEncrypted, IsKey,
+ AD_Table_ID)
);
//
if (seqNo == 1 && IsIdentifier) {
@@ -366,7 +364,8 @@ public class ModelClassGenerator
int displayType, int AD_Reference_ID, int fieldLength,
String defaultValue, String ValueMin, String ValueMax, String VFormat,
String Callout, String Name, String Description,
- boolean virtualColumn, boolean IsEncrypted, boolean IsKey)
+ boolean virtualColumn, boolean IsEncrypted, boolean IsKey,
+ int AD_Table_ID)
{
Class> clazz = ModelInterfaceGenerator.getClass(columnName, displayType, AD_Reference_ID);
String dataType = ModelInterfaceGenerator.getDataTypeName(clazz, displayType);
@@ -393,64 +392,21 @@ public class ModelClassGenerator
// 1) Must understand which class to reference
if (DisplayType.isID(displayType) && !IsKey)
{
- if (displayType == DisplayType.TableDir
- || (displayType == DisplayType.Search && AD_Reference_ID == 0))
+ String fieldName = ModelInterfaceGenerator.getFieldName(columnName);
+ String referenceClassName = ModelInterfaceGenerator.getReferenceClassName(AD_Table_ID, columnName, displayType, AD_Reference_ID);
+ //
+ if (fieldName != null && referenceClassName != null)
{
- //begin [ 1785001 ] Using ModelPackage of EntityType to Generate Model Class - vpj-cd
- String tableName = columnName.substring(0, columnName.length()-3);
- String referenceClassName = "I_"+columnName.substring(0, columnName.length()-3);
-
- MTable table = MTable.get(Env.getCtx(), tableName);
- if (table != null)
- {
- String entityType = table.getEntityType();
- if (!"D".equals(entityType))
- {
- for (int i = 0; i < entityTypes.length; i++)
- {
- if (entityTypes[i].getEntityType().equals(entityType))
- {
- String modelpackage = entityTypes[i].getModelPackage();
- if (modelpackage != null)
- {
- referenceClassName = modelpackage+".I_"+columnName.substring(0, columnName.length()-3);
- break;
- }
- }
- }
- }
- //end [ 1785001 ]
- sb.append(NL)
- .append("\tpublic "+referenceClassName+" get").append(tableName).append("() throws RuntimeException ").append(NL)
- .append(" {").append(NL)
- // TODO - here we can implement Lazy loading or Cache of class
- .append(" Class> clazz = MTable.getClass("+referenceClassName+".Table_Name);").append(NL)
- .append(" ").append(referenceClassName).append(" result = null;").append(NL)
- .append(" try {").append(NL)
- .append(" Constructor> constructor = null;").append(NL)
- // .append(" try {").append(NL)
- .append(" constructor = clazz.getDeclaredConstructor(new Class[]{Properties.class, int.class, String.class});").append(NL)
- // .append(" } catch (NoSuchMethodException e) {").append(NL)
- // .append(" log.warning(\"No transaction Constructor for \" + clazz + \" Exception[\" + e.toString() + \"]\");").append(NL)
- // .append(" }").append(NL)
- // TODO - here we can implement Lazy loading or Cache of record. Like in Hibernate, objects can be loaded on demand or when master object is loaded.
- .append(" result = ("+referenceClassName+")constructor.newInstance(new Object[] {getCtx(), new Integer(get"+columnName+"()), get_TrxName()});").append(NL)
- .append(" } catch (Exception e) {").append(NL)
- .append(" log.log(Level.SEVERE, \"(id) - Table=\" + Table_Name + \",Class=\" + clazz, e);").append(NL)
- .append(" log.saveError(\"Error\", \"Table=\" + Table_Name + \",Class=\" + clazz);").append(NL)
- .append(" throw new RuntimeException( e );").append(NL)
- .append(" }").append(NL)
- .append(" return result;").append(NL)
- .append(" }").append(NL)
- ;
- }
+ sb.append(NL)
+ .append("\tpublic "+referenceClassName+" get").append(fieldName).append("() throws RuntimeException").append(NL)
+ .append(" {").append(NL)
+ .append("\t\treturn ("+referenceClassName+")MTable.get(getCtx(), "+referenceClassName+".Table_Name)").append(NL)
+ .append("\t\t\t.getPO(get"+columnName+"(), get_TrxName());")
+ /**/
+ .append("\t}").append(NL)
+ ;
// Add imports:
- addImportClass(java.lang.reflect.Constructor.class);
- addImportClass(java.util.logging.Level.class);
addImportClass(clazz);
- } else {
- // TODO - Handle other types
- //sb.append("\tpublic I_"+columnName+" getI_").append(columnName).append("(){return null; };");
}
}
diff --git a/base/src/org/adempiere/util/ModelInterfaceGenerator.java b/base/src/org/adempiere/util/ModelInterfaceGenerator.java
index f314b8404a..f84200cb25 100644
--- a/base/src/org/adempiere/util/ModelInterfaceGenerator.java
+++ b/base/src/org/adempiere/util/ModelInterfaceGenerator.java
@@ -45,6 +45,7 @@ import java.util.logging.Level;
import org.adempiere.exceptions.DBException;
import org.compiere.Adempiere;
import org.compiere.model.MEntityType;
+import org.compiere.model.MQuery;
import org.compiere.model.MTable;
import org.compiere.util.CLogMgt;
import org.compiere.util.CLogger;
@@ -63,8 +64,13 @@ import org.compiere.util.Env;
* better formating of generated source
* BF [ 1787833 ] ModelInterfaceGenerator: don't write timestamp
* FR [ 1803309 ] Model generator: generate get method for Search cols
+ * BF [ 1817768 ] Isolate hardcoded table direct columns
+ * https://sourceforge.net/tracker/?func=detail&atid=879332&aid=1817768&group_id=176962
* FR [ 2343096 ] Model Generator: Improve Reference Class Detection
* BF [ 2528434 ] ModelInterfaceGenerator: generate getters for common fields
+ * --
+ * FR [ 2848449 ] ModelClassGenerator: Implement model getters
+ * https://sourceforge.net/tracker/?func=detail&atid=879335&aid=2848449&group_id=176962
* @author Victor Perez, e-Evolution
* FR [ 1785001 ] Using ModelPackage of EntityType to Generate Model Class
*/
@@ -97,11 +103,6 @@ public class ModelInterfaceGenerator
/** Logger */
private static CLogger log = CLogger.getCLogger(ModelInterfaceGenerator.class);
- /** EntityType */
- private static final MEntityType[] entityTypes = MEntityType.getEntityTypes(Env.getCtx());
-
-
-
public ModelInterfaceGenerator(int AD_Table_ID, String directory, String packageName) {
this.packageName = packageName;
// create column access methods
@@ -275,7 +276,7 @@ public class ModelInterfaceGenerator
isUpdateable, isMandatory, displayType,
AD_Reference_Value_ID, fieldLength, defaultValue,
ValueMin, ValueMax, VFormat, Callout, Name,
- Description, virtualColumn, IsEncrypted, IsKey));
+ Description, virtualColumn, IsEncrypted, IsKey, AD_Table_ID));
}
}
catch (SQLException e)
@@ -316,7 +317,7 @@ public class ModelInterfaceGenerator
int displayType, int AD_Reference_ID, int fieldLength,
String defaultValue, String ValueMin, String ValueMax,
String VFormat, String Callout, String Name, String Description,
- boolean virtualColumn, boolean IsEncrypted, boolean IsKey)
+ boolean virtualColumn, boolean IsEncrypted, boolean IsKey, int AD_Table_ID)
{
Class> clazz = getClass(columnName, displayType, AD_Reference_ID);
String dataType = getDataTypeName(clazz, displayType);
@@ -351,41 +352,13 @@ public class ModelInterfaceGenerator
if (isGenerateModelGetter(columnName) && DisplayType.isID(displayType) && !IsKey)
{
- if (displayType == DisplayType.TableDir
- || (displayType == DisplayType.Search && AD_Reference_ID == 0))
+ String fieldName = getFieldName(columnName);
+ String referenceClassName = getReferenceClassName(AD_Table_ID, columnName, displayType, AD_Reference_ID);
+ //
+ if (fieldName != null && referenceClassName != null)
{
- String referenceClassName = "I_"+columnName.substring(0, columnName.length()-3);
- //begin [ 1785001 ] Using ModelPackage of EntityType to Generate Model Class - vpj-cd
- String tableName = columnName.substring(0, columnName.length()-3);
-
- MTable table = MTable.get(Env.getCtx(), tableName);
- if (table != null)
- {
- String entityType = table.getEntityType();
- if (!"D".equals(entityType))
- {
- for (int i = 0; i < entityTypes.length; i++)
- {
- if (entityTypes[i].getEntityType().equals(entityType))
- {
- String modelpackage = entityTypes[i].getModelPackage();
- if (modelpackage != null)
- {
- referenceClassName = modelpackage+".I_"+columnName.substring(0, columnName.length()-3);
- break;
- }
- }
- }
- }
- //end [ 1785001 ]
-
- sb.append("\n")
- .append("\tpublic "+referenceClassName+" get").append(tableName).append("() throws RuntimeException;")
- ;
- }
- } else {
- // TODO - Handle other types
- //sb.append("\tpublic I_"+columnName+" getI_").append(columnName).append("(){return null; };");
+ sb.append("\n")
+ .append("\tpublic "+referenceClassName+" get").append(fieldName).append("() throws RuntimeException;");
}
}
addImportClass(clazz);
@@ -571,7 +544,7 @@ public class ModelInterfaceGenerator
* @param columnName
* @return true if a setter method should be generated
*/
- public boolean isGenerateSetter(String columnName)
+ public static boolean isGenerateSetter(String columnName)
{
return
!"AD_Client_ID".equals(columnName)
@@ -586,9 +559,9 @@ public class ModelInterfaceGenerator
/**
* @param columnName
- * @return true if a model getter method should be generated
+ * @return true if a model getter method (method that is returning referenced PO) should be generated
*/
- public boolean isGenerateModelGetter(String columnName)
+ public static boolean isGenerateModelGetter(String columnName)
{
return
!"AD_Client_ID".equals(columnName)
@@ -597,6 +570,166 @@ public class ModelInterfaceGenerator
&& !"UpdatedBy".equals(columnName)
;
}
+
+ /**
+ *
+ * @param AD_Table_ID
+ * @param toEntityType
+ * @return true if a model getter method (method that is returning referenced PO) should be generated
+ */
+ public static boolean isGenerateModelGetterForEntity(int AD_Table_ID, String toEntityType)
+ {
+ final String fromEntityType = DB.getSQLValueString(null, "SELECT EntityType FROM AD_Table where AD_Table_ID=?", AD_Table_ID);
+ final MEntityType fromEntity = MEntityType.get(Env.getCtx(), fromEntityType);
+ final MEntityType toEntity = MEntityType.get(Env.getCtx(), toEntityType);
+ return
+ // Same entities
+ fromEntityType.equals(toEntityType)
+ // Both are system entities
+ || (fromEntity.isSystemMaintained() && toEntity.isSystemMaintained())
+ // Not Sys Entity referencing a Sys Entity
+ || (!fromEntity.isSystemMaintained() && toEntity.isSystemMaintained())
+ ;
+ }
+
+ /**
+ * Get EntityType Model Package.
+ * @author Victor Perez - [ 1785001 ] Using ModelPackage of EntityType to Generate Model Class
+ * @param entityType
+ * @return
+ */
+ public static String getModelPackage(String entityType)
+ {
+ if ("D".equals(entityType))
+ return null;
+
+ for (MEntityType entity : MEntityType.getEntityTypes(Env.getCtx()))
+ {
+ if (entity.getEntityType().equals(entityType))
+ {
+ return entity.getModelPackage();
+ }
+ }
+ return null;
+ }
+
+ public static String getFieldName(String columnName)
+ {
+ String fieldName;
+ if (columnName.endsWith("_ID_To"))
+ fieldName = columnName.substring(0, columnName.length() - 6) + "_To";
+ else
+ fieldName = columnName.substring(0, columnName.length() - 3);
+ return fieldName;
+ }
+
+ public static String getReferenceClassName(int AD_Table_ID, String columnName, int displayType, int AD_Reference_ID)
+ {
+ String referenceClassName = null;
+ //
+ if (displayType == DisplayType.TableDir
+ || (displayType == DisplayType.Search && AD_Reference_ID == 0))
+ {
+ String refTableName = MQuery.getZoomTableName(columnName); // teo_sarca: BF [ 1817768 ] Isolate hardcoded table direct columns
+ referenceClassName = "I_"+refTableName;
+
+ MTable table = MTable.get(Env.getCtx(), refTableName);
+ if (table != null)
+ {
+ String entityType = table.getEntityType();
+ String modelpackage = getModelPackage(entityType) ;
+ if (modelpackage != null)
+ {
+ referenceClassName = modelpackage+"."+referenceClassName;
+ }
+ if (!isGenerateModelGetterForEntity(AD_Table_ID, entityType))
+ {
+ referenceClassName = null;
+ }
+ }
+ else
+ {
+ throw new RuntimeException("No table found for "+refTableName);
+ }
+ }
+ else if (displayType == DisplayType.Table
+ || (displayType == DisplayType.Search && AD_Reference_ID > 0))
+ {
+ // TODO: HARDCODED: do not generate model getter for Fact_Acct.Account_ID
+ if (AD_Table_ID == 270 && columnName.equals("Account_ID"))
+ return null;
+ // TODO: HARDCODED: do not generate model getter for GL_DistributionLine.Account_ID
+ if (AD_Table_ID == 707 && columnName.equals("Account_ID"))
+ return null;
+ //
+ final String sql = "SELECT t.TableName, t.EntityType, ck.AD_Reference_ID"
+ +" FROM AD_Ref_Table rt"
+ +" INNER JOIN AD_Table t ON (t.AD_Table_ID=rt.AD_Table_ID)"
+ +" INNER JOIN AD_Column ck ON (ck.AD_Table_ID=rt.AD_Table_ID AND ck.AD_Column_ID=rt.AD_Key)"
+ +" WHERE rt.AD_Reference_ID=?"
+ ;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try
+ {
+ pstmt = DB.prepareStatement(sql, null);
+ pstmt.setInt(1, AD_Reference_ID);
+ rs = pstmt.executeQuery();
+ if (rs.next())
+ {
+ final String refTableName = rs.getString(1);
+ final String entityType = rs.getString(2);
+ final int refDisplayType = rs.getInt(3);
+ if (refDisplayType == DisplayType.ID)
+ {
+ referenceClassName = "I_"+refTableName;
+ String modelpackage = getModelPackage(entityType);
+ if (modelpackage != null)
+ {
+ referenceClassName = modelpackage+"."+referenceClassName;
+ }
+ if (!isGenerateModelGetterForEntity(AD_Table_ID, entityType))
+ {
+ referenceClassName = null;
+ }
+ }
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new DBException(e, sql);
+ }
+ finally
+ {
+ DB.close(rs, pstmt);
+ rs = null; pstmt = null;
+ }
+ }
+ else if (displayType == DisplayType.Location)
+ {
+ referenceClassName = "I_C_Location";
+ }
+ else if (displayType == DisplayType.Locator)
+ {
+ referenceClassName = "I_M_Locator";
+ }
+ else if (displayType == DisplayType.Account)
+ {
+ referenceClassName = "I_C_ValidCombination";
+ }
+ else if (displayType == DisplayType.PAttribute)
+ {
+ referenceClassName = "I_M_AttributeSetInstance";
+ }
+ else
+ {
+ // TODO - Handle other types
+ //sb.append("\tpublic I_"+columnName+" getI_").append(columnName).append("(){return null; };");
+ }
+ //
+ return referenceClassName;
+ }
+
/**
* String representation
diff --git a/base/src/org/compiere/model/MQuery.java b/base/src/org/compiere/model/MQuery.java
index 900a2eda6b..47d5e260c2 100644
--- a/base/src/org/compiere/model/MQuery.java
+++ b/base/src/org/compiere/model/MQuery.java
@@ -226,6 +226,8 @@ public class MQuery implements Serializable
return "C_BPartner_Location_ID";
if (columnName.equals("Account_ID"))
return "C_ElementValue_ID";
+ if (columnName.equals("C_LocFrom_ID") || columnName.equals("C_LocTo_ID"))
+ return "C_Location_ID";
// Fix "*_To" columns
if (columnName.toUpperCase().endsWith("TO_ID")) {
return columnName.substring(0, columnName.length()-5)+"_ID";
@@ -233,7 +235,7 @@ public class MQuery implements Serializable
if (columnName.toUpperCase().endsWith("_TO_ID")) {
return columnName.substring(0, columnName.length()-6)+"_ID";
}
- if (columnName.equals("AD_OrgBP_ID"))
+ if (columnName.equals("AD_OrgBP_ID") || columnName.equals("AD_OrgTrx_ID"))
return "AD_Org_ID";
// See also GridTab.validateQuery
//