/****************************************************************************** * Product: Posterita Ajax UI * * Copyright (C) 2007 Posterita Ltd. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * Posterita Ltd., 3, Draper Avenue, Quatre Bornes, Mauritius * * or via info@posterita.org or http://www.posterita.org/ * *****************************************************************************/ package org.adempiere.webui.panel; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.logging.Level; import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.ClientInfo; import org.adempiere.webui.component.Grid; import org.adempiere.webui.component.GridFactory; import org.adempiere.webui.component.Label; import org.adempiere.webui.component.Row; import org.adempiere.webui.component.Rows; import org.adempiere.webui.component.Textbox; import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.window.Dialog; import org.compiere.minigrid.ColumnInfo; import org.compiere.minigrid.IDColumn; import org.compiere.minigrid.UUIDColumn; import org.compiere.model.GridField; import org.compiere.model.I_C_ElementValue; import org.compiere.model.MColumn; import org.compiere.model.MLookupFactory; import org.compiere.model.MReference; import org.compiere.model.MTab; import org.compiere.model.MTable; import org.compiere.model.PO; import org.compiere.model.Query; import org.compiere.util.DB; import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.KeyNamePair; import org.compiere.util.Msg; import org.compiere.util.Util; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zul.Borderlayout; import org.zkoss.zul.Cell; import org.zkoss.zul.Center; import org.zkoss.zul.Div; import org.zkoss.zul.North; import org.zkoss.zul.Separator; import org.zkoss.zul.South; import org.zkoss.zul.Vbox; /** * Zk Port * @author Elaine * @version InfoGeneral.java Adempiere Swing UI 3.4.1 */ public class InfoGeneralPanel extends InfoPanel implements EventListener { /** * */ private static final long serialVersionUID = 624139753237845647L; private Textbox txt1; private Textbox txt2; private Textbox txt3; private Textbox txt4; private Label lbl1; private Label lbl2; private Label lbl3; private Label lbl4; /** String Array of Column Info */ private ColumnInfo[] m_generalLayout; /** list of query columns */ private ArrayList m_queryColumns = new ArrayList(); /** list of query columns (SQL) */ private ArrayList m_queryColumnsSql = new ArrayList(); private Borderlayout layout; private Vbox southBody; private int noOfParameterColumn; public InfoGeneralPanel(String queryValue, int windowNo,String tableName,String keyColumn, boolean multipleSelection, String whereClause) { this(queryValue, windowNo, tableName, keyColumn, multipleSelection, whereClause, true, null); } public InfoGeneralPanel(String queryValue, int windowNo,String tableName,String keyColumn, boolean multipleSelection, String whereClause, boolean lookup, GridField field) { super(windowNo, tableName, keyColumn, multipleSelection, whereClause, lookup, 0, queryValue); setGridfield(field); setTitle(Msg.getMsg(Env.getCtx(), "Info")); try { init(); initComponents(); p_loadedOK = initInfo (); processQueryValue(); } catch (Exception e) { log.log(Level.SEVERE, e.getMessage(), e); return; } // Elaine 2008/12/15 int no = contentPanel.getRowCount(); setStatusLine(Integer.toString(no) + " " + Msg.getMsg(Env.getCtx(), "SearchRows_EnterQuery"), false); setStatusDB(Integer.toString(no)); // if (queryValue != null && queryValue.length() > 0) { if (!isAutoComplete) { MTable table = MTable.get(Env.getCtx(), p_tableName); if ( table.getIdentifierColumns().length > 1 && !p_tableName.startsWith("AD_")) // 32 AD tables with identifiers containing _ { String separator = I_C_ElementValue.Table_Name.equalsIgnoreCase(p_tableName) ? "-" : "_"; if (txt2.isVisible()) { String[] values = queryValue.split("["+separator+"]"); if (values != null && values.length == 2) { txt1.setValue(values[0]); txt2.setValue(values[1]); } } } } executeQuery(); renderItems(); } if (ClientInfo.isMobile()) { ClientInfo.onClientInfo(this, this::onClientInfo); } } private void processQueryValue() { if (queryValue != null && queryValue.length() > 0) { Textbox[] txts = new Textbox[] {txt1, txt2, txt3, txt4}; int i = 0; for(Textbox t : txts) { if (t != null && t.isVisible()) { if (isAutoComplete) { if (!Util.isEmpty(autoCompleteSearchColumn)) { if (!autoCompleteSearchColumn.equals(m_queryColumns.get(i))) continue; } } t.setValue(queryValue); testCount(); if (m_count <= 0) t.setValue(null); else break; if (isAutoComplete) break; } i++; } if (m_count <= 0 && !isAutoComplete) { txt1.setValue(queryValue); } } } private void initComponents() { Grid grid = GridFactory.newGridLayout(); ZKUpdateUtil.setWidth(grid, "100%"); ZKUpdateUtil.setVflex(grid, "min"); layoutParameterGrid(grid); layout = new Borderlayout(); ZKUpdateUtil.setWidth(layout, "100%"); ZKUpdateUtil.setHeight(layout, "100%"); layout.setStyle("position: relative"); this.appendChild(layout); North north = new North(); layout.appendChild(north); north.appendChild(grid); ZKUpdateUtil.setVflex(north, "min"); Center center = new Center(); layout.appendChild(center); Div div = new Div(); div.appendChild(contentPanel); ZKUpdateUtil.setWidth(contentPanel, "100%"); ZKUpdateUtil.setVflex(contentPanel, true); contentPanel.setSizedByContent(true); center.appendChild(div); ZKUpdateUtil.setVflex(div, "1"); ZKUpdateUtil.setHflex(div, "1"); ZKUpdateUtil.setVflex(center, "1"); South south = new South(); layout.appendChild(south); southBody = new Vbox(); ZKUpdateUtil.setWidth(southBody, "100%"); south.appendChild(southBody); southBody.appendChild(new Separator()); southBody.appendChild(confirmPanel); southBody.appendChild(statusBar); ZKUpdateUtil.setVflex(south, "min"); } protected void layoutParameterGrid(Grid grid) { noOfParameterColumn = getNoOfParameterColumn(); Rows rows = new Rows(); grid.appendChild(rows); Row row = new Row(); rows.appendChild(row); row.appendChild(lbl1.rightAlign()); row.appendChild(txt1); ZKUpdateUtil.setHflex(txt1, "1"); if (row.getChildren().size() % noOfParameterColumn == 0) row = rows.newRow(); row.appendChild(lbl2.rightAlign()); row.appendChild(txt2); ZKUpdateUtil.setHflex(txt2, "1"); if (row.getChildren().size() % noOfParameterColumn == 0) row = rows.newRow(); Cell cell = new Cell(); cell.setAlign("right"); cell.setValign("middle"); Div ldiv = new Div(); ldiv.appendChild(lbl3); cell.appendChild(ldiv); row.appendChild(cell); cell = new Cell(); cell.setValign("middle"); cell.appendChild(txt3); row.appendChild(cell); ZKUpdateUtil.setHflex(txt3, "1"); if (row.getChildren().size() % noOfParameterColumn == 0) row = rows.newRow(); cell = new Cell(); cell.setAlign("right"); cell.setValign("middle"); ldiv = new Div(); ldiv.appendChild(lbl4); cell.appendChild(ldiv); row.appendChild(cell); cell = new Cell(); cell.setValign("middle"); cell.appendChild(txt4); row.appendChild(cell); ZKUpdateUtil.setHflex(txt4, "1"); } private int getNoOfParameterColumn() { if (ClientInfo.maxWidth(ClientInfo.EXTRA_SMALL_WIDTH-1)) return 2; else if (ClientInfo.maxWidth(ClientInfo.SMALL_WIDTH-1)) return 4; else if (ClientInfo.maxWidth(ClientInfo.MEDIUM_WIDTH-1)) return 6; else return 8; } private void init() { txt1 = new Textbox(); txt2 = new Textbox(); txt3 = new Textbox(); txt4 = new Textbox(); txt1.setWidgetAttribute(AdempiereWebUI.WIDGET_INSTANCE_NAME, "textbox1"); txt2.setWidgetAttribute(AdempiereWebUI.WIDGET_INSTANCE_NAME, "textbox2"); txt3.setWidgetAttribute(AdempiereWebUI.WIDGET_INSTANCE_NAME, "textbox3"); txt4.setWidgetAttribute(AdempiereWebUI.WIDGET_INSTANCE_NAME, "textbox4"); lbl1 = new Label(); lbl2 = new Label(); lbl3 = new Label(); lbl4 = new Label(); } private boolean initInfo () { if (!initInfoTable()) return false; // Prepare table StringBuilder where = new StringBuilder(); if(m_gridfield != null) { MReference ref = m_gridfield.getAD_Reference_Value_ID() > 0 ? MReference.get(Env.getCtx(), m_gridfield.getAD_Reference_Value_ID()) : null; if(ref == null || !ref.isShowInactiveRecords()) { where = new StringBuilder(p_tableName).append(".").append("IsActive='Y'"); } } if (p_whereClause.length() > 0) { if(where.length() > 0) where.append(" AND "); where.append(" (").append(p_whereClause).append(")"); } prepareTable(m_generalLayout, p_tableName, where.toString(), "2"); contentPanel.repaint(); // Set & enable Fields lbl1.setValue(Util.cleanAmp(Msg.translate(Env.getCtx(), m_queryColumns.get(0).toString()))); if (m_queryColumns.size() > 1) { lbl2.setValue(Msg.translate(Env.getCtx(), m_queryColumns.get(1).toString())); } else { lbl2.setVisible(false); txt2.setVisible(false); } if (m_queryColumns.size() > 2) { lbl3.setValue(Msg.translate(Env.getCtx(), m_queryColumns.get(2).toString())); } else { lbl3.setVisible(false); txt3.setVisible(false); hideCell(lbl3); hideCell(txt3); } if (m_queryColumns.size() > 3) { lbl4.setValue(Msg.translate(Env.getCtx(), m_queryColumns.get(3).toString())); } else { lbl4.setVisible(false); txt4.setVisible(false); hideCell(lbl4); hideCell(txt4); } return true; } private void hideCell(Component comp) { Component p = comp.getParent(); while (p != null) { if (p instanceof Cell) { p.setVisible(false); break; } p = p.getParent(); } } private boolean initInfoTable () { MTable table = MTable.get(Env.getCtx(), p_tableName); String uucolName = PO.getUUIDColumnName(p_tableName); boolean hasWindowAndTab = new Query(Env.getCtx(), MTab.Table_Name, " AD_Table_ID = ? ", null) .setParameters(table.getAD_Table_ID()) .match(); // Get Query Columns String sqlqc = "SELECT c.ColumnName, t.AD_Table_ID, t.TableName, c.ColumnSql " + "FROM AD_Table t" + " INNER JOIN AD_Column c ON (t.AD_Table_ID=c.AD_Table_ID)" + "WHERE c.AD_Reference_ID IN (10,14)" + " AND t.TableName=? "; // #1 if(hasWindowAndTab) { // Displayed in Window sqlqc += " AND EXISTS (SELECT * FROM AD_Field f " + " WHERE f.AD_Column_ID=c.AD_Column_ID " + " AND f.IsDisplayed='Y' AND f.IsEncrypted='N' AND f.ObscureType IS NULL) "; } sqlqc += " ORDER BY c.IsIdentifier DESC, c.IsSelectionColumn Desc, c.AD_Reference_ID, c.SeqNoSelection, c.SeqNo"; int AD_Table_ID = 0; String tableName = null; PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(sqlqc, null); pstmt.setString(1, p_tableName); rs = pstmt.executeQuery(); while (rs.next()) { m_queryColumns.add(rs.getString(1)); String columnSql = rs.getString(4); if (columnSql != null && columnSql.length() > 0 && columnSql.contains("@")) columnSql = "NULL"; if (columnSql != null && columnSql.contains("@")) columnSql = Env.parseContext(Env.getCtx(), -1, columnSql, false, true); String qualified = p_tableName+"."+rs.getString(1); if (columnSql != null && columnSql.length() > 0) m_queryColumnsSql.add(columnSql); else m_queryColumnsSql.add(qualified); if (AD_Table_ID == 0) { AD_Table_ID = rs.getInt(2); tableName = rs.getString(3); } } } catch (SQLException e) { log.log(Level.SEVERE, sqlqc, e); return false; } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } // Minimum check if (m_queryColumns.size() == 0) { Dialog.error(p_WindowNo, "Error", Msg.getMsg(Env.getCtx(),"NoQueryColumnsFound")); log.log(Level.SEVERE, "No query columns found"); return false; } if (log.isLoggable(Level.FINEST)) log.finest("Table " + tableName + ", ID=" + AD_Table_ID + ", QueryColumns #" + m_queryColumns.size()); // Only 4 Query Columns while (m_queryColumns.size() > 4) { m_queryColumns.remove(m_queryColumns.size()-1); m_queryColumnsSql.remove(m_queryColumnsSql.size()-1); } // Set Title String title = null; if (table.isUUIDKeyTable()) title = Msg.translate(Env.getCtx(), uucolName); else { title = Msg.translate(Env.getCtx(), tableName + "_ID"); // best bet if (title.endsWith("_ID")) title = Msg.translate(Env.getCtx(), tableName); // second best bet } setTitle(getTitle() + " " + title); // Get Display Columns int AD_Window_ID = 0; if (table.getAD_Window_ID() > 0) { AD_Window_ID = table.getAD_Window_ID(); } else { AD_Window_ID = table.getWindowIDFromMenu(); } ArrayList list = new ArrayList(); StringBuilder sqlc = new StringBuilder().append( "SELECT c.ColumnName, c.AD_Reference_ID, c.IsKey, "); // 1-3 if(hasWindowAndTab) { // 4 sqlc.append(" f.IsDisplayed, "); } else { sqlc.append(" 'Y', "); } sqlc.append(" c.AD_Reference_Value_ID, c.ColumnSql, c.AD_Column_ID " // 5-7 + "FROM AD_Column c" + " INNER JOIN AD_Table t ON (c.AD_Table_ID=t.AD_Table_ID)"); if(hasWindowAndTab) { sqlc.append(" INNER JOIN AD_Tab tab ON (t.AD_Table_ID=tab.AD_Table_ID)" + " INNER JOIN AD_Field f ON (tab.AD_Tab_ID=f.AD_Tab_ID AND f.AD_Column_ID=c.AD_Column_ID) "); } sqlc.append( "WHERE t.AD_Table_ID=? "); if(hasWindowAndTab) { sqlc.append(" AND tab.IsSortTab='N' " + " AND tab.Ad_Tab_ID=(SELECT MIN(mt.AD_Tab_ID) FROM AD_tab mt WHERE mt.AD_Window_ID=? AND mt.AD_Table_ID=t.AD_Table_ID AND mt.IsActive='Y')" + " AND (c.IsKey='Y' OR " + " (f.IsEncrypted='N' AND f.ObscureType IS NULL))"); } else { sqlc.append(" AND (c.IsKey='Y' " + " OR c.IsIdentifier='Y' " + " OR c.IsParent='Y' " + " OR c.IsSelectionColumn='Y' " + " OR Upper(c.ColumnName) IN ('NAME','VALUE','DESCRIPTION','DOCUMENTNO') " + " OR Upper(c.ColumnName) Like '%_NAME' " + " OR Upper(c.ColumnName) Like '%_Value') "); } sqlc.append(" AND c.IsActive = 'Y' " + "ORDER BY "); if (table.isUUIDKeyTable() || p_keyColumn.endsWith("_UU")) sqlc.append("CASE WHEN c.columnname=").append(DB.TO_STRING(uucolName)).append("THEN 0 ELSE 1 END"); else sqlc.append("c.IsKey DESC"); if(hasWindowAndTab) sqlc.append(", f.SeqNo"); try { pstmt = DB.prepareStatement(sqlc.toString(), null); pstmt.setInt(1, AD_Table_ID); if(hasWindowAndTab) pstmt.setInt(2, AD_Window_ID); rs = pstmt.executeQuery(); boolean keyDefined = false; while (rs.next()) { String columnName = rs.getString(1); int displayType = rs.getInt(2); boolean isKey = rs.getString(3).equals("Y"); boolean isDisplayed = rs.getString(4).equals("Y"); int AD_Reference_Value_ID = rs.getInt(5); String columnSql = rs.getString(6); if (columnSql != null && columnSql.length() > 0 && (columnSql.startsWith(MColumn.VIRTUAL_UI_COLUMN_PREFIX) || columnSql.startsWith(MColumn.VIRTUAL_SEARCH_COLUMN_PREFIX))) columnSql = "NULL"; if (columnSql != null && columnSql.contains("@")) columnSql = Env.parseContext(Env.getCtx(), -1, columnSql, false, true); if (columnSql == null || columnSql.length() == 0) columnSql = tableName+"."+columnName; int AD_Column_ID = rs.getInt(7); // Default StringBuffer colSql = new StringBuffer(columnSql); Class colClass = null; if (isKey && !keyDefined) colClass = IDColumn.class; else if (uucolName.equals(columnName) && (table.isUUIDKeyTable() || p_keyColumn.endsWith("_UU"))) { colClass = UUIDColumn.class; keyDefined = true; } else if (!isDisplayed) ; else if (displayType == DisplayType.YesNo) colClass = Boolean.class; else if (displayType == DisplayType.Amount) colClass = BigDecimal.class; else if (displayType == DisplayType.Number || displayType == DisplayType.Quantity) colClass = Double.class; else if (displayType == DisplayType.Integer) colClass = Integer.class; else if (displayType == DisplayType.String || displayType == DisplayType.Text || displayType == DisplayType.Memo) colClass = String.class; else if (DisplayType.isDate(displayType)) colClass = Timestamp.class; // ignore Binary, Button, ID, RowID else if (displayType == DisplayType.List || displayType == DisplayType.RadiogroupList || displayType == DisplayType.Payment) { if (Env.isBaseLanguage(Env.getCtx(), "AD_Ref_List")) colSql = new StringBuffer("(SELECT l.Name FROM AD_Ref_List l WHERE l.AD_Reference_ID=") .append(AD_Reference_Value_ID).append(" AND l.Value=").append(columnSql) .append(") AS ").append(columnName); else colSql = new StringBuffer("(SELECT t.Name FROM AD_Ref_List l, AD_Ref_List_Trl t " + "WHERE l.AD_Ref_List_ID=t.AD_Ref_List_ID AND l.AD_Reference_ID=") .append(AD_Reference_Value_ID).append(" AND l.Value=").append(columnSql) .append(" AND t.AD_Language='").append(Env.getAD_Language(Env.getCtx())) .append("') AS ").append(columnName); colClass = String.class; } if (colClass != null) { list.add(new ColumnInfo(Msg.translate(Env.getCtx(), columnName), colSql.toString(), colClass, true, columnName )); if (log.isLoggable(Level.FINEST)) log.finest("Added Column=" + columnName); } else if (isDisplayed && DisplayType.isLookup(displayType) && !(displayType == DisplayType.ChosenMultipleSelectionTable || displayType == DisplayType.ChosenMultipleSelectionSearch || displayType == DisplayType.ChosenMultipleSelectionList)) { ColumnInfo colInfo = createLookupColumnInfo(Msg.translate(Env.getCtx(), columnName), columnName, displayType, AD_Reference_Value_ID, AD_Column_ID, colSql.toString()); if (colInfo != null) { list.add(colInfo); } else { if (log.isLoggable(Level.FINEST)) log.finest("Not Added Column=" + columnName); } } else if (log.isLoggable(Level.FINEST)) log.finest("Not Added Column=" + columnName); } } catch (SQLException e) { log.log(Level.SEVERE, sqlc.toString(), e); return false; } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } if (list.size() == 0) { Dialog.error(p_WindowNo, "Error", "No Info Columns"); log.log(Level.SEVERE, "No Info for AD_Table_ID=" + AD_Table_ID + " - " + sqlc.toString()); return false; } if (log.isLoggable(Level.FINEST)) log.finest("InfoColumns #" + list.size()); // Convert ArrayList to Array m_generalLayout = new ColumnInfo[list.size()]; list.toArray(m_generalLayout); return true; } @Override public String getSQLWhere() { StringBuffer sql = new StringBuffer(); addSQLWhere (sql, 0, txt1.getText().toUpperCase()); addSQLWhere (sql, 1, txt2.getText().toUpperCase()); addSQLWhere (sql, 2, txt3.getText().toUpperCase()); addSQLWhere (sql, 3, txt4.getText().toUpperCase()); return sql.toString(); } private void addSQLWhere(StringBuffer sql, int index, String value) { if (!(value.equals("")) && index < m_queryColumns.size()) { // Angelo Dabala' (genied) nectosoft: [2893220] avoid to append string parameters directly because of special chars like quote(s) sql.append(" AND UPPER(").append(m_queryColumnsSql.get(index).toString()).append(") LIKE ?"); } } /** * Get SQL WHERE parameter * @param f field * @return sql part */ private String getSQLText (Textbox f) { String s = f.getText().toUpperCase(); if (!s.endsWith("%")) s += "%"; if (log.isLoggable(Level.FINE)) log.fine( "String=" + s); return s; } // getSQLText protected void resetParameters() { txt1.setValue(""); txt2.setValue(""); txt3.setValue(""); txt4.setValue(""); } /** * Set Parameters for Query. * (as defined in getSQLWhere) * @param pstmt statement * @param forCount for counting records * @throws SQLException */ protected void setParameters(PreparedStatement pstmt, boolean forCount) throws SQLException { int index = 1; if (txt1.getText().length() > 0) pstmt.setString(index++, getSQLText(txt1)); if (txt2.getText().length() > 0) pstmt.setString(index++, getSQLText(txt2)); if (txt3.getText().length() > 0) pstmt.setString(index++, getSQLText(txt3)); if (txt4.getText().length() > 0) pstmt.setString(index++, getSQLText(txt4)); } // setParameters @Override protected void insertPagingComponent() { southBody.insertBefore(paging, southBody.getFirstChild()); layout.invalidate(); } protected void onClientInfo() { if (layout != null && layout.getNorth() != null && layout.getNorth().getFirstChild() instanceof Grid) { int t = getNoOfParameterColumn(); if (t > 0 && noOfParameterColumn > 0 && t != noOfParameterColumn) { Grid grid = (Grid) layout.getNorth().getFirstChild(); grid.getRows().detach(); layoutParameterGrid(grid); this.invalidate(); } } } protected ColumnInfo createLookupColumnInfo(String name, String columnName, int AD_Reference_ID, int AD_Reference_Value_ID, int AD_Column_ID, String columnSql) { // MLookupInfo lookupInfo = MLookupFactory.getLookupInfo(Env.getCtx(), p_WindowNo, AD_Column_ID, AD_Reference_ID, Env.getLanguage(Env.getCtx()), columnName, // AD_Reference_Value_ID, false, null); // String displayColumn = lookupInfo.DisplayColumn; // String keyColumn = lookupInfo.KeyColumn; MTable table = MTable.get(Env.getCtx(), p_tableName); MColumn column = table.getColumn(columnName); String embedded; if (AD_Reference_Value_ID > 0) { embedded = MLookupFactory.getLookup_TableEmbed(Env.getLanguage(Env.getCtx()), columnName, p_tableName, AD_Reference_Value_ID); } else { if (column.isVirtualColumn()) embedded = MLookupFactory.getLookup_TableDirEmbed(Env.getLanguage(Env.getCtx()), columnName, p_tableName, column.getColumnSQL()); else embedded = MLookupFactory.getLookup_TableDirEmbed(Env.getLanguage(Env.getCtx()), columnName, p_tableName, columnName); } embedded = "(" + embedded + ")"; if (embedded.contains("@")) embedded = "NULL"; ColumnInfo columnInfo = null; if (columnName.endsWith("_ID") && !column.isVirtualColumn()) columnInfo = new ColumnInfo(name, embedded, KeyNamePair.class, true, false, p_tableName+"."+columnName, columnName); else columnInfo = new ColumnInfo(name, embedded, String.class, true, false, null, columnName); return columnInfo; } }