OAF日志使用总结

    本文的完成感谢葛严大神授权使用LogUtil类,其次感谢Tavor大神的EBS OAF开发日志(见: EBS OAF开发中日志(Logging) )。

    日志的使用是一门极大的学问,若读者有兴趣,可以自行选择阅读以下参考:

    最佳日志实践(v2.0)

    Java 日志管理最佳实践

    Logging 最佳实践

    首先,尽量不要在代码中使用System.out.println()方法直接打印日志,虽然这在开发过程中极其便捷,但是也带来了以下影响

    1.大量的 sop  将产生大量的IO操作   同时在生产环境中 无法合理的控制是否需要输出

    2.专门的日志框架可以合理的控制日志 实现 文件  DB 控制分片容量 Email预警等。

    OAF 框架本身也提供了日志级别,同时提供了日志输出方法fnd_log.STRING和writeDiagnostics方法,但是我觉得不太好用,日志级别倒是极好用的。

    参考:Logging in OAF Pages – A Technical Note!

             OAF: How to add logging / debug messages in Oracle Application Framework(需翻|墙)

             writeDiagnostics() method of OAF(需翻|墙)

    所以,只需要开启了FND 诊断(配置文件:FND 诊断),在地址栏输入 &AFLOG_LEVEL=ERROR(或其他日志级别)

    如:http://devapp.xxxxxx.com:8080/OA_HTML/OAHOMEPAGE&AFLOG_LEVEL=ERROR即可在网页下方看到输出的日志了,在网页中显示日志使用的writeDiagnostics()方法。

    关于JDeveloper集成log4j可参考我的另一篇博客:(OAF)jdeveloper集成log4j并将日志输出到指定文件并写入数据库

    集成Logback同理,两种方式需要的配置文件也自行百度。

    LogUtil类如下

package cux.oracle.apps.cux.common.util;

import java.sql.CallableStatement;
import java.sql.SQLException;

import java.text.SimpleDateFormat;

import java.util.Date;

import oracle.apps.fnd.framework.OAException;
import oracle.apps.fnd.framework.OAFwkConstants;
import oracle.apps.fnd.framework.server.OADBTransaction;
import oracle.apps.fnd.framework.server.OAEntityImpl;
import oracle.apps.fnd.framework.server.OAViewObjectImpl;
import oracle.apps.fnd.framework.server.OAViewRowImpl;
import oracle.apps.fnd.framework.webui.OAPageContext;

import oracle.jbo.ApplicationModule;
import oracle.jbo.Row;
import oracle.jbo.ViewObject;



/**
 * LogUtil 实现Log输出的核心逻辑,它可以在CO,AM,EO,VO中,以及
 * 任何可以获得OADBTransaction的地方使用。
 *
 * 静态工程方法of负责初始化log的内容,内容分为类名称和详细内容,详细内容
 * 可以是一个String,也可以是一个二维数组。内容经过格式化后,通过print输出。
 * print方法在输出的时候,必须依靠LogContext参数,来确定输出方式和输出层次上。
 *
 * 对于LogContext参数,传入的是一个实现了LogContext接口的一个calss,通常,
 * 对于特定的功能开发最好新建一个这样的calss,这样此功能开发的log输出就可以
 * 很好地和其他log输出分离,且可以独立地控制输出方式和输出层次。
 *
 * Log内容包含三种信息:类名称,必须具有。方法名称和变量的值,非必须。
 *
 * GEYAN 2010-01-06
 */

/**
 * 2010-06-05 改进建议:
 * 是否命令行输出,可通过 isDeveloperMode;诊断输出也没有必要依靠一个开关,因为它本身就具有开关。
 * 因而完全可以将 LogUtil 和 LogContext 构成的手柄模式合并为单类,或者至少可以进一步简化。
 */

/**
 * 2010-06-08  
 * 新的版本不再依赖 LogContext ,代之以 logLevel 默认值,以及可以改变此默认值的 Builder 模式实现。
 * 而输出开关则依赖Oracle本身的机制,isDeveloperMode 和 isLoggingEnabled ,
 * 这样更加合理,且不会影响性能。
 * 
 */
public class LogUtil
{

  private String[][] output = new String[1][2];
  private String className;
  
    //private final static org.slf4j.Logger logger = LoggerFactory.getLogger(LogUtil.class.getName());

  /**
   * 输出层次定义, logLevel, 
   * 是 oracle.apps.fnd.framework.OAFwkConstants 的六个常量, 值依次从1到6.
   * OAFwkConstants.STATEMENT
   * OAFwkConstants.PROCEDURE
   * OAFwkConstants.EVENT
   * OAFwkConstants.EXCEPTION
   * OAFwkConstants.ERROR
   * OAFwkConstants.UNEXPECTED
   * 
   * 系统中默认的是 OAFwkConstants.UNEXPECTED,故默认层次不能选择UNEXPECTED。
   * 
   * 这里默认为 OAFwkConstants.ERROR,通过logLevel方法来更改其所需的值。
   * 
   * &aflog_level=ERROR
   */
  private int logLevel = OAFwkConstants.ERROR;

  private LogUtil(String str,
                  Object object)
  {
    output = new String[1][2];
    output[0][0] = str;

    this.className = getClassName(object);
  }

  private LogUtil(String[][] stra,
                  Object object)
  {
    output = new String[stra.length][2];
    System.arraycopy(stra, 0, output, 0, output.length);

    this.className = getClassName(object);
  }

  public LogUtil logLevel(int logLevel)
  {
    this.logLevel = logLevel;
    return this;
  }

  /**
   * object的作用是得到类的名称,它可以是this指针,也可以是String形式的类名称。
   * 
   * 通常object的参数的值是this,通过this.getClass().getName()来获取类名称。
   * 但是在static方法里,this指针不可用,只有以String形式传入类名称。
   */
  private static String getClassName(Object object)
  {
    if (java.lang.String.class.equals(object.getClass()))
    {
      return object.toString();
    }
    return object.getClass().getName();
  }

  /**
   * 两个静态工厂方法of,分别构造单个字符串和二维字符串数组类型的 LogUtil 实例。
   * 
   * object参数应该传入当前调用所在的类的this指针,通过this得到类名称。
   * 在static方法中,则以String形式传入类名称。
   */
  public static LogUtil of(String str,
                           Object object)
  {
    return new LogUtil(str, object);
  }

  public static LogUtil of(String[][] stra,
                           Object object)
  {
    return new LogUtil(stra, object);
  }
  
  private String getCurrentTime()
  {
    Date currentTime = new Date(System.currentTimeMillis());
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(currentTime);
  }

  private String getOutput()
  {
//    String result = 
//      "
-------------------------------------------------> log : [" + getCurrentTime() + "]
";
//
//    result = result + " & " + "class" + "  is  " + "[" + className + "]
";
//
//    if (output.length == 1 && (output[0][1] == null || "".equals(output[0][1])))
//    {
//      return result + " " + output[0][0] + "
";
//    }
//
//    for (int i = 0; i < output.length; i++)
//    {
//      if (output[i] != null)
//      {
//        result = result + " & " + output[i][0] + "  is  " + output[i][1] + "
";
//      }
//    }
//
//    return result;
         StringBuffer result = new StringBuffer();
         result.append("
-------------------------------------------------> log : ["
                         + getCurrentTime() + "]
");
                         
         result.append(" & " + "class" + "  is  " + "[" + className + "]
");
         
         //等价
//         StackTraceElement[] trace = new Throwable().getStackTrace();
         StackTraceElement[] trace = Thread.currentThread().getStackTrace();
         for (int len=0; len<trace.length; len++){
             // trace的长度为从函数入口到print方法执行过的函数层数
             // 下标为0的元素是上一行语句的信息, 下标为1的才是调用print的地方的信息
             StackTraceElement tmp = trace[len];
             
             if(tmp.getClassName().length()>=6 && "oracle".equals(tmp.getClassName().substring(0,6)))
             //函数的入口为java.lang.Thread.run
             //中间的层次结构太长
             //故循环到标准方法即停止,仅显示客户化调用
                break;
             
             result.append(" & "+ tmp.getClassName() + "." + tmp.getMethodName() 
                 + "(" + tmp.getFileName() + ":" + tmp.getLineNumber() + ")
" );
         }
    
         if (output.length == 1 && (output[0][1] == null || "".equals(output[0][1]))) {
             return result + " " + output[0][0] + "
";
         }
    
         for (int i = 0; i < output.length; i++) {
             if (output[i] != null) {
                     result.append(" & " + output[i][0] + "  is  "
                                     + output[i][1] + "
");
             }
         }
    
         return result.toString();

  }

  //  /**
  //   * 2010-06-08 
  //   * 不再推荐以下的委托LogContext对象的几个版本,推荐使用不带LogContext的版本。
  //   * 
  //   * 提供在CO,AM,VO,EO,中常用的版本,和一个通用版本OADBTransaction tsn。
  //   * 
  //   * */
  //  public void print(OAPageContext pageContext, LogContext logContext)
  //  {
  //    String output = getOutput();
  //    
  //    if(logContext.isCommandLineLog())
  //    {
  //      System.out.print(output);
  //    }
  //    
  //    if(logContext.isDiagnosticLog())
  //    {
  //      if(pageContext.isLoggingEnabled(logContext.getLogLevel()))
  //      {
  //        pageContext.writeDiagnostics(this.className, output, logContext.getLogLevel());
  //      }
  //    }
  //  
  //  }
  //
  //  public void print(OADBTransaction tsn, LogContext logContext)
  //  {
  //    String output = getOutput();
  //  
  //    if (logContext.isCommandLineLog())
  //    {
  //      System.out.print(output);
  //    }
  //
  //    if(logContext.isDiagnosticLog())
  //    {
  //      if(tsn.isLoggingEnabled(logContext.getLogLevel()))
  //      {
  //         tsn.writeDiagnostics(this.className, output, logContext.getLogLevel());
  //      }
  //    }
  //  
  //  }
  //
  //  public void print(OAApplicationModule am, LogContext logContext)
  //  {
  //    OADBTransaction tsn = am.getOADBTransaction();
  //    print(tsn, logContext);
  //  }
  //  
  //  public void print(OAViewObjectImpl vo, LogContext logContext)
  //  {
  //    OADBTransaction tsn = (OADBTransaction)vo.getDBTransaction();
  //    print(tsn, logContext);
  //  }
  //
  //  public void print(OAViewRowImpl voRow, LogContext logContext)
  //  {
  //    OAViewObjectImpl vo = (OAViewObjectImpl)voRow.getViewObject();
  //    OADBTransaction tsn = (OADBTransaction)vo.getDBTransaction();
  //    print(tsn, logContext);
  //  }
  //
  //  public void print(OAEntityImpl eo, LogContext logContext)
  //  {
  //    OADBTransaction tsn = (OADBTransaction)eo.getDBTransaction();
  //    print(tsn, logContext);
  //  }  

  /**
   * 2010-06-08 推荐使用以下几个不带LogContext的版本。
   * 
   * 提供在 CO,AM,VO,EO,中常用的版本,和一个通用版本 OADBTransaction tsn。
   */
  public void print(OAPageContext pageContext)
  {
    OADBTransaction tsn = pageContext.getRootApplicationModule().getOADBTransaction();
    print(tsn);
  }

  public void print(OADBTransaction tsn)
  {
    String output = getOutput();

    
    //开发者模式
    if (tsn.isDeveloperMode())
    {
    
      System.out.print(output);

      //Update By hongbo
    //不再使用System.out.print方法,代之以LogBack
// logger.info(className);
//System.out.println("className is "+className);
// logger.info(output);

//        org.slf4j.Logger log = LoggerFactory.getLogger(className);
//        log.info(output);
 //End
        
    }

    if (tsn.isLoggingEnabled(this.logLevel))
    {
      tsn.writeDiagnostics(this.className, output, this.logLevel);
      cux_log_messages(tsn, output);
      
    }
      //Add By hongbo,20160525
      //此处使用集成slf4j实现日志输出,具体实现可自行百度
      //将Logback或者log4j相关jar包引入工程目录 (服务器放入$JAVA_TOP目录)
      //并配置相关配置文件logback.xml或log4j.propertites 放入工程根目录,即myprojects目录
//       org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(className);
//       log.info(output);
       //此处直接使用log4j实现日志输出
//      org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(className); 
//      logger.info(output);
      //End
       
       

    //    /*
    //     * 通过配置文件 CUX_LOG_MESSAGES_FILE,取得log文件的全路径。
    //     * 例如 /usr/tmp/user_log_temp.log,再将日志写入此文件。
    //     */
    //    String logFile = tsn.getProfile("CUX_LOG_MESSAGES_FILE");
    //    if (logFile != null && !"".equals(logFile))
    //    {
    //      FileUtil.write(logFile, getOutput());
    //    }

  }

  private void cux_log_messages(OADBTransaction tsn,
                                String output)
  {
    try
    {
        //cux_common_util_pkg各位自己去实现,此处就不罗列了
      String sql = 
        "begin cux_common_util_pkg.cux_log_messages(p_log_sequence => :1,
" + "                                   p_module => :2,
" + 
        "                                   p_log_level => :3,
" + 
        "                                   p_message_text => :4); end;";

      CallableStatement cs = tsn.createCallableStatement(sql, 1);
      cs.setLong(1, System.currentTimeMillis());
      cs.setString(2, this.className);
      cs.setInt(3, this.logLevel);
      cs.setString(4, output);
      cs.execute();
      cs.close();
    }
    catch (SQLException e)
    {
      throw OAException.wrapperException(e);
    }
  }

  public void print(ApplicationModule am)
  {
    OADBTransaction tsn = (OADBTransaction) am.getTransaction();
    print(tsn);
  }

  public void print(ViewObject vo)
  {
    OADBTransaction tsn = (OADBTransaction) ((OAViewObjectImpl) vo).getDBTransaction();
    print(tsn);
  }

  public void print(Row row)
  {
    OAViewObjectImpl vo = (OAViewObjectImpl) ((OAViewRowImpl) row).getViewObject();
    OADBTransaction tsn = (OADBTransaction) vo.getDBTransaction();
    print(tsn);
  }

  public void print(OAEntityImpl eo)
  {
    OADBTransaction tsn = (OADBTransaction) eo.getDBTransaction();
    print(tsn);
  }

    public void printScreen(OAPageContext pageContext) {
            OADBTransaction tsn = 
                pageContext.getRootApplicationModule().getOADBTransaction();
            printScreen(tsn);
        }
    
        public void printScreen(ApplicationModule am) {
            OADBTransaction tsn = (OADBTransaction)am.getTransaction();
            printScreen(tsn);
        }
    
        public void printScreen(OADBTransaction tsn) {
            String output = getOutput();
    
            if (tsn.isDeveloperMode()) {
                System.out.print(output);
            }
    
            if (tsn.isLoggingEnabled(this.logLevel)) {
                tsn.writeDiagnostics(this.className, output, this.logLevel);
            }
        }
}

调用方法如下:

CO中LogUtil.of(stringContent or String[][] , this ).print(pageContext);

其他如EO,AM,VO等直接LogUtil.of(String or String[][], this).print(this);

网页显示日志在开启诊断之后在地址栏后加入 &aflog_level=error(日志级别自定义)即可。

VO对象常用类:ModelUtil

package cuxA.oracle.apps.cux.common.util;


import java.sql.SQLException;

import oracle.apps.fnd.common.MessageToken;
import oracle.apps.fnd.framework.OAApplicationModule;
import oracle.apps.fnd.framework.OAException;
import oracle.apps.fnd.framework.OANLSServices;
import oracle.apps.fnd.framework.server.OADBTransaction;
import oracle.apps.fnd.framework.server.OAViewObjectImpl;
import oracle.apps.fnd.framework.webui.OAPageContext;

import oracle.jbo.ApplicationModule;
import oracle.jbo.Row;
import oracle.jbo.ViewLink;
import oracle.jbo.ViewObject;


/**
 * 提供mvc之Model端的常用工具。
 * 
 * geyan 2010-01-06
 */
public class ModelUtil {
    private ModelUtil() {
    }

    public static final String CLASS_NAME = 
        "com.ncgc.oracle.apps.cux.por.util.ModelUtil";

    /**
     * 以一种简短的方式获得 OANLSServices,进而获得OANLSServices提供的一系列服务。
     */
    public static OANLSServices getNls(OAApplicationModule am) {
        return am.getOADBTransaction().getOANLSServices();
    }

    public static OANLSServices getNls(OADBTransaction tsn) {
        return tsn.getOANLSServices();
    }

    public static oracle.jbo.domain.Number stringToNumber(String str) {
        try {
            return new oracle.jbo.domain.Number(str);
        } catch (SQLException e) {
            throw OAException.wrapperException(e);
        }
    }

    public static void clearVoCache(ViewObject vo) {
        vo.clearCache();
        vo.setMaxFetchSize(-1);
        vo.setWhereClauseParams(null);
        vo.setWhereClause("1=2");
        vo.executeQuery();
    }

    public static void clearVoCache(ApplicationModule am, String voName) {
        ViewObject vo = findVo(am, voName);
        clearVoCache(vo);
    }

    public static ApplicationModule getChildAm(ApplicationModule parentAm, 
                                               String childAmName) {
        String[] amNames = parentAm.getApplicationModuleNames();
        for (int i = 0; i < amNames.length; i++) {
            if (amNames[i].endsWith(childAmName)) {
                return parentAm.findApplicationModule(amNames[i]);
            } else {
                ApplicationModule childAm = 
                    parentAm.findApplicationModule(amNames[i]);
                ApplicationModule am = getChildAm(childAm, childAmName);
                if (am != null) {
                    return am;
                }
            }
        }

        return null;
    }

    public static ApplicationModule getChildAm(OAPageContext pageContext, 
                                               String childAmName) {
        ApplicationModule parentAm = pageContext.getRootApplicationModule();
        return ModelUtil.getChildAm(parentAm, childAmName);
    }

    public static ViewObject findVo(ApplicationModule am, String voName) {
        ViewObject vo = am.findViewObject(voName);

        if (vo == null) {
            MessageToken[] errTokens = 
            { new MessageToken("OBJECT_NAME", voName), };
            throw new OAException("AK", "FWK_TBX_OBJECT_NOT_FOUND", errTokens);
        }

        return vo;
    }

    public static ApplicationModule findAm(ApplicationModule parentAm, 
                                           String amName) {
        ApplicationModule am = parentAm.findApplicationModule(amName);

        if (am == null) {
            MessageToken[] errTokens = 
            { new MessageToken("OBJECT_NAME", amName), };
            throw new OAException("AK", "FWK_TBX_OBJECT_NOT_FOUND", errTokens);
        }

        return am;
    }

    /**
     * 此方法返回 vo 当前 fetch 的所有行。
     */
    public static Row[] getVoFetchedRows(ApplicationModule am, String voName) {
        ViewObject vo = findVo(am, voName);
        return getVoFetchedRows(vo);
    }

    public static Row[] getVoFetchedRows(ViewObject vo) {
        String[][] stra = 
        { { "method", "getVoFetchedRows" }, { "vo.getName()", vo.getName() }, 
          { "vo.isExecuted()", vo.isExecuted() + "" }, 
          { "vo.getFetchedRowCount()", vo.getFetchedRowCount() + "" }, };
        LogUtil.of(stra, CLASS_NAME).print(vo);

        if (!vo.isExecuted()) {
            return new Row[0];
        }

        vo.setRangeStart(0);
        vo.setRangeSize(-1);

        return vo.getAllRowsInRange() != null ? vo.getAllRowsInRange() : 
               new Row[0];
    }

    /**
     * 通过 attributeValue 删除Vo当前Fetch到的行,一行或多行。
     */
    public static void removeVoFetchedRow(ViewObject vo, String attributeName, 
                                          String attributeValue) {
        Row[] rows = getVoFetchedRows(vo);

        String[][] stra = 
        { { "method", "removeVoFetchedRow" }, { "attributeName", 
                                                attributeName }, 
          { "attributeValue", attributeValue }, 
          { "rows.length", rows.length + "" }, };
        LogUtil.of(stra, CLASS_NAME).print(vo);

        for (int i = 0; i < rows.length; i++) {
            String value$row = rows[i].getAttribute(attributeName).toString();
            if (value$row.equals(attributeValue)) {
                rows[i].remove();
            }
        }
    }

    public static void removeVoFetchedRow(ApplicationModule am, String voName, 
                                          String pkAttributeName, 
                                          String pkValue) {
        ViewObject vo = findVo(am, voName);
        removeVoFetchedRow(vo, pkAttributeName, pkValue);
    }

    /**
     * 返回 "多选框"选择的行。
     * 此方法简化了"未选择行","返回行为空"的处理。
     */
    public static Row[] getVoFilteredRows(ApplicationModule am, String voName, 
                                          String attribute) {
        ViewObject vo = findVo(am, voName);
        return getVoFilteredRows(vo, attribute);
    }

    /**
     * 返回 "多选框"选择的行。
     * 此方法简化了"未选择行","返回行为空"的处理。
     */
    public static Row[] getFilteredRows(OAApplicationModule am, String voName, 
                                        String attribute) {
        ViewObject vo = findVo(am, voName);

        // 若vo尚无任何行,则返回 0长度数组
        vo.reset();
        if (!vo.hasNext()) {
            return new Row[0];
        }

        Row[] rows = vo.getFilteredRows(attribute, "Y");

        return rows != null && rows.length > 0 ? rows : new Row[0];
    }

    public static Row[] getVoFilteredRows(ViewObject vo, String attribute) {
        // 若vo尚无任何行,则返回 0长度数组
        vo.reset();
        if (!vo.hasNext()) {
            return new Row[0];
        }

        Row[] rows = vo.getFilteredRows(attribute, "Y");

        return rows != null && rows.length > 0 ? rows : new Row[0];
    }

    public static Row getVoFirstFilteredRow(ApplicationModule am, 
                                            String voName, String attribute) {
        OAViewObjectImpl vo = (OAViewObjectImpl)findVo(am, voName);
        return getVoFirstFilteredRow(vo, attribute);
    }

    public static Row getVoFirstFilteredRow(OAViewObjectImpl vo, 
                                            String attribute) {
        return vo.getFirstFilteredRow(attribute, "Y");
    }

    /**
     * remove当前am中的一个vo。
     */
    public static void removeVo(ApplicationModule am, String voName) {
        ViewObject vo = findVo(am, voName);
        vo.remove();
    }

    /**
     * 返回"下一个"序号,给定当前VO和其序号所在的列,返回现有列最大值加1的数字。
     */
    public static Integer getNextSeqNum(ViewObject vo, String attributeName) {
        Row[] rows = getVoFetchedRows(vo);
        if (rows == null || rows.length == 0) {
            return 1;
        }

        // 否则,依次比较并返回 "最大值 + 1"
        int result = 0;
        for (int i = 0; i < rows.length; i++) {
            Object seqNum$row = rows[i].getAttribute(attributeName);
            if (seqNum$row == null) {
                continue;
            }

            int seqNumRowInt = Integer.valueOf(seqNum$row.toString());
            result = seqNumRowInt > result ? seqNumRowInt : result;
        }

        return result + 1;
    }

    public static Integer getNextSeqNum(ApplicationModule am, String voName, 
                                        String attributeName) {
        ViewObject vo = ModelUtil.findVo(am, voName);
        return getNextSeqNum(vo, attributeName);
    }

    public static void commit(OAApplicationModule am, boolean isClearEoCache) {
        OADBTransaction tsn = am.getOADBTransaction();
        commit(tsn, isClearEoCache);
    }

    public static void commit(OADBTransaction tsn, boolean isClearEoCache) {
        boolean isClearCacheOnCommit = tsn.isClearCacheOnCommit();

        // ClearCacheOnCommit
        tsn.setClearCacheOnCommit(isClearEoCache);
        try {
            tsn.commit();
        } catch (OAException e) {
            throw e;
        }

        // 恢复原先设置
        tsn.setClearCacheOnCommit(isClearCacheOnCommit);
    }

    public static void rollback(OAApplicationModule am, 
                                boolean isClearEoCache) {
        OADBTransaction tsn = am.getOADBTransaction();
        rollback(tsn, isClearEoCache);
    }

    public static void rollback(OADBTransaction tsn, boolean isClearEoCache) {
        boolean isClearCacheOnRollback = tsn.isClearCacheOnRollback();

        // ClearCacheOnRollback
        tsn.setClearCacheOnRollback(isClearEoCache);
        if (tsn.isDirty()) {
            tsn.rollback();
        }

        // 恢复原先设置
        tsn.setClearCacheOnRollback(isClearCacheOnRollback);
    }

    public static ViewObject createVo(ApplicationModule am, String voName, 
                                      String voDefine) {
        ViewObject vo = am.findViewObject(voName);
        if (vo != null) {
            return vo;
        }

        return am.createViewObject(voName, voDefine);
    }

    public static Object[] getVoWhereClauseParams(ViewObject vo) {
        Object[] objects = vo.getWhereClauseParams();
        if (objects == null) {
            return null;
        }

        Object[] result = new Object[objects.length];
        for (int i = 0; i < objects.length; i++) {
            if (objects[i].getClass().isArray()) {
                Object[] params = (Object[])objects[i];
                Object param$index = params[0];
                Object param$value = params[1];

                result[i] = param$value;
            } else {
                Object param$value = objects[i];

                result[i] = param$value;
            }
        }

        return result;
    }

    public static void outputVo(ViewObject vo) {
        String[][] stra = 
        { { "method", "outputVo" }, { "vo.getName()", vo.getName() }, 
          { "vo.getFullName()", vo.getFullName() }, 
          { "vo.getDefFullName()", vo.getDefFullName() }, 
          { "vo.isExecuted()", vo.isExecuted() + "" }, 
          { "vo.getRangeSize()", vo.getRangeSize() + "" }, 
          { "vo.getRangeStart()", vo.getRangeStart() + "" }, 
          { "vo.getFetchedRowCount()", vo.getFetchedRowCount() + "" }, 
          { "vo.getCurrentRowIndex()", vo.getCurrentRowIndex() + "" }, 
          { "vo.getMaxFetchSize()", vo.getMaxFetchSize() + "" }, 
          { "vo.getWhereClause()", vo.getWhereClause() }, 
          { "getVoWhereClauseParams(vo)", 
            arrayToString(getVoWhereClauseParams(vo)) }, 
          { "vo.getOrderByClause()", vo.getOrderByClause() }, 
          { "vo.getQuery()", vo.getQuery() }, };
        LogUtil.of(stra, CLASS_NAME).print(vo);
    }

    public static void outputVo(ApplicationModule am, String voName) {
        ViewObject vo = ModelUtil.findVo(am, voName);
        outputVo(vo);
    }

    public static String arrayToString(Object[] arrary) {
        if (arrary == null || arrary.length == 0) {
            return null;
        }

        String result = "";
        for (int i = 0; i < arrary.length; i++) {
            result = result + arrary[i] + " , ";
        }

        return " [ " + result + " ] ";
    }

    public static void displayModels(ApplicationModule am) {
        String[] ams = am.getApplicationModuleNames();
        for (int i = 0; i < ams.length; i++) {
            ApplicationModule am$i = am.findApplicationModule(ams[i]);
            String[][] stra = 
            { { "method", "displayModels" }, { "for", i + " --> display ApplicationModule" }, 
              { "parent AM", am.getFullName() }, 
              { "child AM Name", am$i.getName() }, 
              { "child AM FullName", am$i.getFullName() }, 
              { "child AM DefFullName", am$i.getDefFullName() }, };
            LogUtil.of(stra, CLASS_NAME).print(am);
        }

        String[] vos = am.getViewObjectNames();
        for (int i = 0; i < vos.length; i++) {
            ViewObject vo$i = am.findViewObject(vos[i]);
            String[][] stra = 
            { { "method", "displayModels" }, { "for", i + " --> display ViewObject" }, 
              { "parent AM", am.getFullName() }, 
              { "child VO Name", vo$i.getName() }, 
              { "child VO FullName", vo$i.getFullName() }, 
              { "child VO DefFullName", vo$i.getDefFullName() }, };
            LogUtil.of(stra, CLASS_NAME).print(am);
        }

        String[] vls = am.getViewLinkNames();
        for (int i = 0; i < vls.length; i++) {
            ViewLink vl$i = am.findViewLink(vls[i]);
            String[][] stra = 
            { { "method", "displayModels" }, { "for", i + " --> display ViewLink" }, 
              { "parent AM", am.getFullName() }, 
              { "child VL Name", vl$i.getName() }, 
              { "child VL FullName", vl$i.getFullName() }, 
              { "child VL DefFullName", vl$i.getDefFullName() }, };
            LogUtil.of(stra, CLASS_NAME).print(am);
        }

        for (int i = 0; i < ams.length; i++) {
            displayModels(am.findApplicationModule(ams[i]));
        }
    }


}

输出VO对象信息:ModelUtil.outputVo(voInstance);

             

原文地址:https://www.cnblogs.com/huanghongbo/p/7466304.html