NC65 查询相关工具类

查询方案工具类:

package nc.vo.pubapp.query2.sql.process;

import java.util.List;
import java.util.Map;

import nc.md.MDBaseQueryFacade;
import nc.md.common.AssociationKind;
import nc.md.model.IAssociation;
import nc.md.model.IAttribute;
import nc.md.model.IBean;
import nc.md.model.IBusinessEntity;
import nc.md.model.ICardinality;
import nc.md.model.MetaDataException;
import nc.ui.querytemplate.filter.IFilter;
import nc.ui.querytemplate.querytree.FromWhereSQL;
import nc.ui.querytemplate.querytree.IQueryScheme;
import nc.vo.bd.meta.IBDObject;
import nc.vo.pub.ISuperVO;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;

/**
 * 查询方案工具类
 * 
 * @since 6.0
 * @version 2010-12-16 上午09:15:39
 * @author chenyyb
 */
public class QuerySchemeUtils {
    
    

  public static String getGroupColumnName(IBean mainBean) {
    
    
    if (mainBean == null) {
    
    
      return "pk_group";
    }
    Map<String, String> bizInterfaceMapInfo =
        ((IBusinessEntity) mainBean).getBizInterfaceMapInfo(IBDObject.class
            .getName());
    if (bizInterfaceMapInfo == null || bizInterfaceMapInfo.isEmpty()) {
    
    
      return "pk_group";
    }
    return bizInterfaceMapInfo.get("pk_group") != null ? bizInterfaceMapInfo
        .get("pk_group") : "pk_group";
  }

  public static String getGroupColumnName(IQueryScheme queryScheme) {
    
    
    IBean mainBean = QuerySchemeUtils.getMainBean(queryScheme);
    return QuerySchemeUtils.getGroupColumnName(mainBean);
  }

  public static IBean getMainBean(IQueryScheme queryScheme) {
    
    
    String beanId = (String) queryScheme.get(QueryConstants.BEAN_ID);
    IBean mainBean = null;
    try {
    
    
      mainBean = MDBaseQueryFacade.getInstance().getBeanByID(beanId);
    }
    catch (MetaDataException e) {
    
    
      ExceptionUtils.wrappException(e);
    }
    return mainBean;
  }

  public static String getMainTableAlias(IQueryScheme queryScheme) {
    
    
    FromWhereSQL fromWhereSql = queryScheme.getTableJoinFromWhereSQL();
    return fromWhereSql.getTableAliasByAttrpath(FromWhereSQL.DEFAULT_ATTRPATH);
  }

  /**
   * 得到查询模板对应元数据的主实体表
   * 
   * @param queryScheme
   * @return
   */
  public static String getMainTableFromBean(IQueryScheme queryScheme) {
    
    
    IBean bean = QuerySchemeUtils.getMainBean(queryScheme);
    return null == bean ? null : bean.getTable().getName();
  }

  public static String getOrgColumnName(IBean mainBean) {
    
    
    if (mainBean == null) {
    
    
      return "pk_org";
    }
    Map<String, String> bizInterfaceMapInfo =
        ((IBusinessEntity) mainBean).getBizInterfaceMapInfo(IBDObject.class
            .getName());
    if (bizInterfaceMapInfo == null || bizInterfaceMapInfo.isEmpty()) {
    
    
      return "pk_org";
    }
    return bizInterfaceMapInfo.get("pk_org") != null ? bizInterfaceMapInfo
        .get("pk_org") : "pk_org";
  }

  public static String getOrgColumnName(IQueryScheme queryScheme) {
    
    
    IBean mainBean = QuerySchemeUtils.getMainBean(queryScheme);
    return QuerySchemeUtils.getOrgColumnName(mainBean);
  }

  // @SuppressWarnings("unchecked")
  // static Map<String, String> getAliasMap(IQueryScheme queryScheme) {
    
    
  // Map<String, String> alias_map =
  // (Map<String, String>) queryScheme.get(QueryConstants.ALIAS_MAP);
  // if (alias_map == null) {
    
    
  // alias_map = new HashMap<String, String>();
  // queryScheme.put(QueryConstants.ALIAS_MAP, alias_map);
  // }
  // return alias_map;
  // }

  @SuppressWarnings("unchecked")
  public static QueryCondition getQueryCondition(String fieldCode,
      IQueryScheme queryScheme) {
    
    
    Map<String, QueryCondition> conditionMap =
        (Map<String, QueryCondition>) queryScheme
            .get(QueryConstants.QUERY_CONDITION);
    if (conditionMap == null) {
    
    
      return null;
    }
    return conditionMap.get(fieldCode);
  }

  public static boolean hasAssociationWithMainEntity(
      Class<? extends ISuperVO> entityClass, IBean mainBean) {
    
    
    List<IAssociation> compositeAssos =
        mainBean.getAssociationsByKind(AssociationKind.Composite,
            ICardinality.ASS_ALL);
    for (IAssociation compositeAsso : compositeAssos) {
    
    
      IBean endBean = compositeAsso.getEndBean();
      boolean retFlag =
          QuerySchemeUtils.hasAssociationWithMainEntity(entityClass, endBean);
      if (retFlag) {
    
    
        return true;
      }
    }
    List<IAssociation> associations = mainBean.getAssociations();
    try {
    
    
      IBean bean =
          MDBaseQueryFacade.getInstance().getBeanByFullClassName(
              entityClass.getName());
      if (bean == mainBean) {
    
    
        return true;
      }
      for (IAssociation association : associations) {
    
    
        if (bean == association.getEndBean()) {
    
    
          return true;
        }
      }
    }
    catch (MetaDataException e) {
    
    
      ExceptionUtils.wrappException(e);
    }
    return false;
  }

  /**
   * 确定指定的实体和查询方案对应的主实体是否存在关联关系,包括聚合关系,引用关系等等。
   * 比如除了正常的主子关联关系,还包括这种关系:比如主实体或子实体的某个字段引用了物料档案
   * 那么也视为该主实体和物料实体存在关联。但是以下这种情况就不算关联关系:主实体或子实体
   * 某个字段引用了物料档案,物料档案引用了物料分类档案,在没有字段直接引用物料分类档案的情况
   * 下不能视为物料分类实体和该主实体存在关联关系。
   * 另外这个方法只提供给公共代码调用,业务代码最好别使用这个方法,否则后果自负
   * 
   * @param entityClass 指定实体对应的class
   * @param queryScheme
   * @return
   */
  public static boolean hasAssociationWithMainEntity(
      Class<? extends ISuperVO> entityClass, IQueryScheme queryScheme) {
    
    
    IBean mainBean = QuerySchemeUtils.getMainBean(queryScheme);
    return QuerySchemeUtils.hasAssociationWithMainEntity(entityClass, mainBean);
  }

  static boolean hasCondition(String fieldCode, IQueryScheme queryScheme) {
    
    
    IFilter[] filters = (IFilter[]) queryScheme.get(IQueryScheme.KEY_FILTERS);
    if (filters == null) {
    
    
      return false;
    }
    for (IFilter filter : filters) {
    
    
      String code = filter.getFilterMeta().getFieldCode();
      if (fieldCode.equals(code)) {
    
    
        return true;
      }
    }
    return false;
  }

  static boolean isAttrOwnToExpandTable(IBean bean, String attrMetaPath) {
    
    
    IAttribute attribute = bean.getAttributeByPath(attrMetaPath);
//    IType dataType = attribute.getDataType();
//    if (MDUtil.isLeafType(dataType)) {
    
    
      IBean beanOfAttr = attribute.getOwnerBean();
      String tableOfBean = beanOfAttr.getTable().getName();
      String tableOfAttr = attribute.getTable().getName();
      if (tableOfBean.equals(tableOfAttr)) {
    
    
        return false;
      }
      return true;
//    }
//    return false;
  }

  static boolean isAttrOwnToExpandTable(IQueryScheme queryScheme,
      String attrMetaPath) {
    
    
    return QuerySchemeUtils.isAttrOwnToExpandTable(
        QuerySchemeUtils.getMainBean(queryScheme), attrMetaPath);
  }
}

权限sql工具类:

package nc.vo.pubapp.query2.sql.process;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Logger;
import nc.impl.pubapp.pattern.database.IDExQueryBuilder;
import nc.md.model.IAttribute;
import nc.md.model.IBean;
import nc.md.model.IBusinessEntity;
import nc.md.model.type.ICollectionType;
import nc.md.util.MDUtil;
import nc.pubitf.rbac.IFunctionPermissionPubService;
import nc.ui.querytemplate.querytree.QTMDUtil;
import nc.ui.querytemplate.querytree.datapower.DataPowerTableQueryService;
import nc.vo.bd.meta.IBDObject;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.pub.BusinessException;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.uap.rbac.constant.IResourceConst;

/**
 * 权限sql工具
 * 
 * @since 6.0
 * @version 2011-3-29 上午10:43:58
 * @author 陈云云
 */
public class PowerSqlUtils {
    
    
  public static interface ITableAliasGetter {
    
    
    String getTableAlias(IAttribute atttibute);
  }

  public static class PowerSqlParameter {
    
    
    private String[] attributes;

    private IBean bean;

    private String tableAlias;

    public PowerSqlParameter(String[] attributes, IBean bean, String tableAlias) {
    
    
      super();
      this.attributes = attributes;
      this.bean = bean;
      this.tableAlias = tableAlias;
    }

    public String[] getAttributes() {
    
    
      return this.attributes;
    }

    public IBean getBean() {
    
    
      return this.bean;
    }

    public String getTableAlias() {
    
    
      return this.tableAlias;
    }

    public void setAttributes(String[] attributes) {
    
    
      this.attributes = attributes;
    }

    public void setBean(IBean bean) {
    
    
      this.bean = bean;
    }

    public void setTableAlias(String tableAlias) {
    
    
      this.tableAlias = tableAlias;
    }

  }

  private Map<String, IAttribute> dpAttributeMap;

  private IBean mainBean;

  public PowerSqlUtils(IBean mainBean) {
    
    
    super();
    this.mainBean = mainBean;
  }

  public PowerSqlUtils(IBean mainBean, String metaPath) {
    
    
    this.mainBean = mainBean;
    IAttribute attribute = this.mainBean.getAttributeByPath(metaPath);
    this.dpAttributeMap = new HashMap<String, IAttribute>();
    if (this.isDataPowerInteresting(attribute)) {
    
    
      this.dpAttributeMap.put(metaPath, attribute);
    }
  }

  // public PowerSqlUtils(IBean mainBean, String[] metaPaths) {
    
    
  // this.mainBean = mainBean;
  // this.dpAttributeMap = new HashMap<String, IAttribute>();
  // for (String metaPath : metaPaths) {
    
    
  // if (metaPath == null) {
    
    
  // continue;
  // }
  // IAttribute attribute = this.mainBean.getAttributeByPath(metaPath);
  // if (this.isDataPowerInteresting(attribute)) {
    
    
  // this.dpAttributeMap.put(metaPath, attribute);
  // }
  // }
  // }

  public PowerSqlUtils(PowerSqlParameter powerSqlParameter) {
    
    
    this.mainBean = powerSqlParameter.getBean();
    String[] attributes = powerSqlParameter.getAttributes();
    for (String metaPath : attributes) {
    
    
      if (metaPath == null) {
    
    
        continue;
      }
      IAttribute attribute = this.mainBean.getAttributeByPath(metaPath);
      if (this.isDataPowerInteresting(attribute)) {
    
    
        this.dpAttributeMap.put(metaPath, attribute);
      }
    }
  }

  public static String generatePowerSql(PowerSqlParameter[] powerSqlParameters) {
    
    
    StringBuffer powerSqls = new StringBuffer();
    for (final PowerSqlParameter powerSqlParameter : powerSqlParameters) {
    
    
      PowerSqlUtils utils = new PowerSqlUtils(powerSqlParameter);
      String powerSql = utils.generatePowerSql(new ITableAliasGetter() {
    
    

        @Override
        public String getTableAlias(IAttribute atttibute) {
    
    
          return powerSqlParameter.getTableAlias();
        }

      });
      powerSqls.append(powerSql);
    }
    return powerSqls.toString();
  }

  public String generatePowerSql() {
    
    
    return this.generatePowerSql(new ITableAliasGetter() {
    
    

      @Override
      public String getTableAlias(IAttribute atttibute) {
    
    
        return atttibute.getTable().getName();
      }

    });
  }

  public String generatePowerSql(ITableAliasGetter aliasGetter) {
    
    
    // StringBuffer powerSql = new StringBuffer();
    // Map<String, String> dpTableMap = this.getDPTableMap();
    // Set<Entry<String, String>> entrySet = dpTableMap.entrySet();
    // for (Entry<String, String> entry : entrySet) {
    
    
    // IAttribute attribute =
    // this.getDPAttributeMap(this.mainBean).get(entry.getKey());
    // String dpTable = entry.getValue();
    // if (StringUtil.isEmptyWithTrim(dpTable)) {
    
    
    // continue;
    // }
    // powerSql.append(" and "
    // + this.generatePowerSql(attribute, entry.getValue(), aliasGetter));
    // }
    // return powerSql.toString();
    return this.generatePowerSql(this.mainBean, aliasGetter);
  }

  public Map<String, String> getDataPowerOperationCodeMap() {
    
    
    Map<String, IAttribute> dpAttrMap = this.getDPAttributeMap(this.mainBean);
    Map<String, String> data_power_operation_map =
        new HashMap<String, String>();
    Set<Entry<String, IAttribute>> entrySet = dpAttrMap.entrySet();
    for (Entry<String, IAttribute> entry : entrySet) {
    
    
      data_power_operation_map.put(entry.getKey(), entry.getValue()
          .getAccessPowerGroup());
    }
    return data_power_operation_map;
  }

  public String getFuncPermissionOrgSql() {
    
    
    return this.getFuncPermissionOrgSql(null);
  }

  public String getFuncPermissionOrgSql(String nodeCode) {
    
    
    StringBuffer sql = new StringBuffer();
    Map<String, String> infMap =
        ((IBusinessEntity) this.mainBean)
            .getBizInterfaceMapInfo(IBDObject.class.getName());
    if (infMap == null || infMap.size() == 0) {
    
    
      return sql.toString();
    }
    String mainTable = this.mainBean.getTable().getName();
    String pk_orgName = mainTable + "." + infMap.get("pk_org");
    IFunctionPermissionPubService functionPermService =
        NCLocator.getInstance().lookup(IFunctionPermissionPubService.class);
    String[] funcPermissionOrgs = null;
    try {
    
    
      funcPermissionOrgs =
          functionPermService.getUserPermissionPkOrgs(AppContext.getInstance()
              .getPkUser(), nodeCode, AppContext.getInstance().getPkGroup());
    }
    catch (BusinessException e) {
    
    
      Logger.error(e);
    }
    if (funcPermissionOrgs == null || funcPermissionOrgs.length == 0) {
    
    
      return " and 1=2";// 如果没有有权限的组织,则查不到数据。
    }
    // IDQueryBuilder builder = new IDQueryBuilder();
    IDExQueryBuilder builder = new IDExQueryBuilder("TEMP_PUBAPPPO_");
    sql.append(builder.buildSQL(pk_orgName, funcPermissionOrgs));
    return " and " + sql.toString();
  }

  /**
   * 抽取数据权限属性关联实体的id
   */
  private String[] extractBeanIDs(List<IAttribute> dpAttrs) {
    
    
    String[] beanIDs = new String[dpAttrs.size()];
    for (int i = 0; i < dpAttrs.size(); i++) {
    
    
      beanIDs[i] = QTMDUtil.getAssociationBean(dpAttrs.get(i)).getID();
    }
    return beanIDs;
  }

  private Map<String, IAttribute> extractDPAttrs(IBean bean, String collPath) {
    
    
    List<IAttribute> attrs = bean.getAttributes();
    Map<String, IAttribute> dataPowerAttrs = new HashMap<String, IAttribute>();
    for (IAttribute attr : attrs) {
    
    
      if (this.isDataPowerInteresting(attr)) {
    
    // 数据权限感兴趣的主表属性
        dataPowerAttrs.put(
            (collPath != null ? collPath + "." : "") + attr.getName(), attr);
      }
      else if (MDUtil.isCollectionType(attr.getDataType())) {
    
    // 分析聚合的子表实体
        ICollectionType ctype = (ICollectionType) attr.getDataType();
        IBean childBean = (IBean) ctype.getElementType();
        dataPowerAttrs.putAll(this.extractDPAttrs(childBean,
            (collPath != null ? collPath + "." : "") + attr.getName()));
      }
    }
    return dataPowerAttrs;
  }

  /**
   * 抽取数据权限属性的operation
   */
  private String[] extractOperations(List<IAttribute> dpAttrs) {
    
    
    String[] operations = new String[dpAttrs.size()];
    for (int i = 0; i < dpAttrs.size(); i++) {
    
    
      operations[i] = QTMDUtil.getDataPowerOperation(dpAttrs.get(i));
    }
    return operations;
  }

  private String findMetaPathByAttr(IAttribute attribute,
      Map<String, IAttribute> attrMap) {
    
    
    // Map<String, IAttribute> attrMap = this.getAttributeMap();
    Set<Entry<String, IAttribute>> entrySet = attrMap.entrySet();
    for (Entry<String, IAttribute> entry : entrySet) {
    
    
      if (entry.getValue() == attribute) {
    
    
        return entry.getKey();
      }
    }
    return null;
  }

  private String generatePowerSql(IAttribute attribute, String dpTableName,
      ITableAliasGetter aliasGetter) {
    
    
    String tableAlias = aliasGetter.getTableAlias(attribute);
    SqlBuilder sql = new SqlBuilder();
    sql.append("(");
    sql.appendIDIsNull(tableAlias + "." + attribute.getColumn().getName());
    sql.append(" or ");
    sql.append(tableAlias);
    sql.append(".");
    sql.append(attribute.getColumn().getName());
    sql.append(" in ");
    sql.append("( select ");
    sql.append(IResourceConst.DATAPERM_SPLITE_PKCOLNAME);
    sql.append(" ");
    sql.append(IResourceConst.DATAPERM_SPLITE_PKCOLNAME);
    sql.append(" from ");
    sql.append(dpTableName);
    sql.append(")");
    sql.append(")");
    return sql.toString();
  }

  private String generatePowerSql(IBean bean, ITableAliasGetter aliasGetter) {
    
    
    StringBuffer powerSql = new StringBuffer();
    Map<String, String> dpTableMap = this.getDPTableMap();
    Set<Entry<String, String>> entrySet = dpTableMap.entrySet();
    for (Entry<String, String> entry : entrySet) {
    
    
      IAttribute attribute = this.getDPAttributeMap(bean).get(entry.getKey());
      String dpTable = entry.getValue();
      if (StringUtil.isEmptyWithTrim(dpTable)) {
    
    
        continue;
      }
      powerSql.append(" and "
          + this.generatePowerSql(attribute, entry.getValue(), aliasGetter));
    }
    return powerSql.toString();
  }

  private Map<String, IAttribute> getDPAttributeMap(IBean bean) {
    
    
    if (this.dpAttributeMap == null) {
    
    
      this.dpAttributeMap = this.extractDPAttrs(bean, null);
    }
    return this.dpAttributeMap;
  }

  private Map<String, String> getDPTableMap() {
    
    
    Map<String, IAttribute> dpAttrs = this.getDPAttributeMap(this.mainBean);
    // return this.getDPTableMap(dpAttrs);
    Map<String, String> dpAttr_dpTable_map = new HashMap<String, String>();
    List<IAttribute> attrs = new ArrayList<IAttribute>(dpAttrs.values());
    String[] dpTables = this.getDPTables(attrs);
    if (dpTables != null && dpTables.length != 0) {
    
    
      for (int i = 0; i < dpTables.length; i++) {
    
    
        dpAttr_dpTable_map.put(this.findMetaPathByAttr(attrs.get(i), dpAttrs),
            dpTables[i]);
      }
    }
    return dpAttr_dpTable_map;
  }

  private String[] getDPTables(List<IAttribute> dpAttrs) {
    
    
    String[] beanIDs = this.extractBeanIDs(dpAttrs);
    String[] operations = this.extractOperations(dpAttrs);
    // 根据beanIDs和operations查询数据权限分表信息,这份信息是会随时间而变化的,所以实时查询
    return new DataPowerTableQueryService().getDataPowerTables(beanIDs,
        operations);
  }

  /**
   * 判断属性是否是数据权限感兴趣的:启用权限控制的引用类型属性(非计算属性)
   */
  private boolean isDataPowerInteresting(IAttribute attr) {
    
    
    return MDUtil.isRefType(attr.getDataType()) && attr.hasAccessPower()
        && !attr.isCalculation();
  }
}

查询方案处理器(没有元数据):

package nc.vo.pubapp.query2.sql.process;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import nc.bs.framework.common.NCLocator;
import nc.impl.pubapp.pattern.database.IDExQueryBuilder;
import nc.md.MDBaseQueryFacade;
import nc.md.common.AssociationKind;
import nc.md.model.IAssociation;
import nc.md.model.IAttribute;
import nc.md.model.IBean;
import nc.md.model.IBusinessEntity;
import nc.md.model.ICardinality;
import nc.md.model.ITable;
import nc.md.model.MetaDataException;
import nc.md.model.type.ICollectionType;
import nc.md.model.type.IRefType;
import nc.md.model.type.IType;
import nc.md.util.MDUtil;
import nc.pubitf.rbac.IFunctionPermissionPubService;
import nc.ui.querytemplate.filter.IFilter;
import nc.ui.querytemplate.querytree.IQuerySQLGenerator;
import nc.ui.querytemplate.querytree.IQueryScheme;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.pub.BusinessException;
import nc.vo.pub.ISuperVO;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.pubapp.query2.sql.process.PowerSqlUtils.ITableAliasGetter;

/**
 * 在有些单据查询的时候,查询模板要查询的表不是固定的,是通过用户输入的条件动态决定的。
 * 这样的话就没有办法把查询模板跟某个元数据组件进行绑定,那么在平台生成sql的时候由于
 * 没有任何元数据信息,所有sql的from部分没有办法拼接,因为无法知道表之间的关联关系。
 * where部分的sql也只提供了单个条件的sql。这个类就是专门用来处理这种非元数据查询模板的
 * sql加工的<p>
 * 使用这个工具的时候,在业务根据用户输入的信息明确要查那个实体时传入以下信息:
 * <li>一个map:所有字段在查询模板中定义的fieldcode和该字段在所查实体中的元数据路径的一个映射,
 * 逻辑条件不需要映射,在后面拼sql的时候会检查,如果map中不存在该字段就把它当逻辑条件,
 * 拼sql的时候不会处理。因为非元数据查询模板大部分是在转单的时候使用的,在转单时这个map由查询模板的提供方构造。
 * <li>待查主实体对应的vo class
 * <li>查询方案Query Scheme
 * <p>
 * 加工sql的方式和元数据查询非常的相似:在拼固定条件的时候sql片段还是业务组自己来拼,
 * 但是业务组可能没有相关表的别名信息,提供{@link #getTableAliasOfFieldCode(String)}方法获取别名
 * 业务组的代码应该按照下面的方式写,和
 * {@link nc.vo.pubapp.query2.sql.process.QuerySchemeProcessor}的使用方式类似:
 * <p>
 * <pre>
 * NonMetaQuerySchemeProcessor qrySchemeProcessor=new
 * NonMetaQuerySchemeProcessor(map,voclass,queryScheme);
 * String alias=qrySchemeProcessor.getTableAliasOfFieldCode
 * ("pu_order_b.pk_org");
 * processor.appendWhere(alias+".bislatest= 'Y'");
 * String fromWherePart=processor.getFinalFromWhere();
 * </pre>
 * 
 * @since 6.0
 * @version 2011-3-23 上午10:10:05
 * @author 陈云云
 */
public class NonMetaQuerySchemeProcessor {
    
    
  private static class QuerySchemeSqlInfo implements Serializable {
    
    
    private static final long serialVersionUID = 3005345864907290411L;

    private StringBuffer addedFromPart = new StringBuffer();

    private StringBuffer addedWherePart = new StringBuffer();

    private boolean appendCurrentGroup = false;

    private StringBuffer mainFromPart = new StringBuffer();

    private boolean needAppendFixPart = true;

    private StringBuffer selectedFromPart = new StringBuffer();

    private StringBuffer selectedWherePart = new StringBuffer();

    /**
     * 存储别名,key:聚合属性名,value:别名
     */
    private Map<String, String> table_alias_map = new HashMap<String, String>();

    QuerySchemeSqlInfo() {
    
    
      // TODO Auto-generated constructor stub
    }

    void clearAddedFromPart() {
    
    
      this.addedFromPart = new StringBuffer();
    }

    void clearAddedWherePart() {
    
    
      this.addedWherePart = new StringBuffer();
    }

    StringBuffer getAddedFromPart() {
    
    
      return this.addedFromPart;
    }

    StringBuffer getAddedWherePart() {
    
    
      return this.addedWherePart;
    }

    StringBuffer getMainFromPart() {
    
    
      return this.mainFromPart;
    }

    StringBuffer getSelectedFromPart() {
    
    
      return this.selectedFromPart;
    }

    StringBuffer getSelectedWherePart() {
    
    
      return this.selectedWherePart;
    }

    Map<String, String> getTable_alias_map() {
    
    
      return this.table_alias_map;
    }

    boolean isAppendCurrentGroup() {
    
    
      return this.appendCurrentGroup;
    }

    boolean isNeedAppendFixPart() {
    
    
      return this.needAppendFixPart;
    }

    void setAppendCurrentGroup(boolean appendCurrentGroup) {
    
    
      this.appendCurrentGroup = appendCurrentGroup;
    }

    void setNeedAppendFixPart(boolean needAppendFixPart) {
    
    
      this.needAppendFixPart = needAppendFixPart;
    }

  }

  private static final char DOT_SIGN = '.';

  private Map<String, IAttribute> attributeMap;

  /**
   * 字段映射,key:查询模板field code,value:元数据路径
   */
  private Map<String, String> columnMapping = new HashMap<String, String>();

  private IBean mainBean;

  private Class<? extends ISuperVO> mainEntityClass;

  private IQueryScheme queryScheme;

  public NonMetaQuerySchemeProcessor(Class<? extends ISuperVO> mainEntityClass,
      Map<String, String> columnMapping, IQueryScheme queryScheme) {
    
    
    super();
    this.columnMapping = columnMapping;
    this.mainEntityClass = mainEntityClass;
    this.queryScheme = queryScheme;
    this.getAlias_map().put(IQuerySQLGenerator.DEFAULT_KEY,
        this.getMainBean().getTable().getName());
  }

  /**
   * 把当前集团拼到sql中
   */
  public void appendCurrentGroup() {
    
    
    this.getQuerySchemeSqlInfo().setAppendCurrentGroup(true);
  }

  /**
   * 追加from部分sql
   * 
   * @param fromPart
   */
  public void appendFrom(String fromPart) {
    
    
    this.getAddedFromPart().append(fromPart);
  }

  public void appendFuncPermissionOrgSql() {
    
    
    String funcode =
        (String) this.queryScheme.get(QueryConstants.KEY_FUNC_NODE);
    if (funcode == null) {
    
    
      return;
    }
    String cuserid = AppContext.getInstance().getPkUser();
    String pkGroup = AppContext.getInstance().getPkGroup();
    // OrgVO[] orgVOs;
    try {
    
    
      String[] orgs =
          NCLocator.getInstance().lookup(IFunctionPermissionPubService.class)
              .getUserPermissionPkOrgs(cuserid, funcode, pkGroup);
      String mainAlias = this.getMainTableAlias();
      String orgColumnName =
          QuerySchemeUtils.getOrgColumnName(this.getMainBean());
      String sql = null;
      if (orgs == null || orgs.length == 0) {
    
    
        SqlBuilder builder = new SqlBuilder();
        builder.append(mainAlias + "." + orgColumnName, "null");
        sql = builder.toString();
      }
      else {
    
    
        // 在组织很多的时候一定要采用临时表
        // IDQueryBuilder builder = new IDQueryBuilder();
        IDExQueryBuilder builder = new IDExQueryBuilder("TEMP_PUBAPPO_");
        sql = builder.buildSQL(mainAlias + "." + orgColumnName, orgs);
      }
      this.getAddedWherePart().append(" and ");
      this.getAddedWherePart().append(sql);
    }
    catch (BusinessException e) {
    
    
      ExceptionUtils.wrappException(e);
    }
  }

  /**
   * 追加where部分sql
   * 
   * @param wherePart
   */
  public void appendWhere(String wherePart) {
    
    
    this.getAddedWherePart().append(wherePart);
  }

  /**
   * 清空之前的加工信息
   */
  public void clearAppendedSqlInfo() {
    
    
    ((QuerySchemeSqlInfo) this.queryScheme.get(QueryConstants.KEY_SQL_INFO
        + "_" + this.getMainTableAlias())).clearAddedFromPart();
    ((QuerySchemeSqlInfo) this.queryScheme.get(QueryConstants.KEY_SQL_INFO
        + "_" + this.getMainTableAlias())).clearAddedWherePart();
  }

  /**
   * 获取加工完成之后的最终sql,包含from和where部分
   * 
   * @return
   */
  public String getFinalFromWhere() {
    
    
    this.constructFixPart();
    StringBuffer sql = new StringBuffer();
    sql.append(" from ");
    sql.append(this.getMainFromPart());
    sql.append(" ");
    sql.append(this.getSelectedFromPart());
    sql.append(" ");
    sql.append(this.getAddedFromPart());
    sql.append(" where ");
    sql.append(this.getSelectedWherePart());
    sql.append(" ");
    sql.append(this.getAddedWherePart());
    return sql.toString();
  }

  /**
   * 获取字段所在表的表别名,在请求别名的时候会检查当前sql中是否存在相关的表,
   * 如果不存在则自动把相关表拼到from部分,并且返回别名,如果存在直接返回别名
   * 
   * @param attrMetaPath 元数据路径
   * @return 表别名
   */
  public String getTableAliasOfAttribute(String attrMetaPath) {
    
    
    String tableAlias = this.findTableAlias(attrMetaPath);
    String aliasPath = null;
    if (StringUtil.isEmptyWithTrim(tableAlias)) {
    
    
      if (QuerySchemeUtils.isAttrOwnToExpandTable(this.getMainBean(),
          attrMetaPath)) {
    
    
        int lastDotIndex =
            attrMetaPath.lastIndexOf(NonMetaQuerySchemeProcessor.DOT_SIGN);
        String parentAttrPath = attrMetaPath.substring(0, lastDotIndex);
        IAttribute attribute =
            this.getMainBean().getAttributeByPath(attrMetaPath);
        String tableName = attribute.getTable().getName();
        aliasPath = parentAttrPath + "." + tableName;
        this.joinExpandTableForicbly(aliasPath);
        tableAlias = this.fetchTableAliasByAliasPath(aliasPath);
      }
      else {
    
    
        int lastDotIndex =
            attrMetaPath.lastIndexOf(NonMetaQuerySchemeProcessor.DOT_SIGN);
        if (lastDotIndex < 0) {
    
    
          throw new RuntimeException("系统错误");/*-=notranslate=-*/
        }
        aliasPath = attrMetaPath.substring(0, lastDotIndex);
        this.joinNormalTableForcibly(aliasPath);
        tableAlias = this.fetchTableAliasByAliasPath(aliasPath);
      }
    }
    return tableAlias;
  }

  /**
   * 获取字段所在表的表别名,在请求别名的时候会检查当前sql中是否存在相关的表,
   * 如果不存在则自动把相关表拼到from部分,并且返回别名,如果存在直接返回别名
   * 
   * @param fieldCode 查询模板中定义的field code
   * @return
   */
  public String getTableAliasOfFieldCode(String fieldCode) {
    
    
    String attrMetaPath = this.columnMapping.get(fieldCode);
    return this.getTableAliasOfAttribute(attrMetaPath);
  }

  String findMetaPathByAttr(IAttribute attribute,
      Map<String, IAttribute> attrMap) {
    
    
    Set<Entry<String, IAttribute>> entrySet = attrMap.entrySet();
    for (Entry<String, IAttribute> entry : entrySet) {
    
    
      if (entry.getValue() == attribute) {
    
    
        return entry.getKey();
      }
    }
    return null;
  }

  Map<String, IAttribute> getAttributeMap() {
    
    
    if (this.attributeMap == null) {
    
    
      this.attributeMap = this.getAttributeMap(this.mainBean, null);
    }
    return this.attributeMap;
  }

  private void appendChildrenDrWhere() {
    
    
    List<IAssociation> associations =
        this.getMainBean().getAssociationsByKind(AssociationKind.Composite,
            ICardinality.ASS_ALL);
    if (associations == null) {
    
    
      return;
    }
    SqlBuilder builder = new SqlBuilder();
    for (IAssociation association : associations) {
    
    
      if (association == null) {
    
    
        continue;
      }
      String startAttr = association.getStartAttribute().getName();
      IBusinessEntity endBean = (IBusinessEntity) association.getEndBean();
      String keyAttr = endBean.getKeyAttribute().getName();
      String aliasPath =
          startAttr + NonMetaQuerySchemeProcessor.DOT_SIGN + keyAttr;
      String childAlias = this.findTableAlias(aliasPath);
      // 只有在子表有条件的之后才会拼dr=0条件
      if (StringUtil.isEmptyWithTrim(childAlias)) {
    
    
        continue;
      }
      builder.append(" and ");
      builder.append(childAlias + ".dr", 0);
    }
    this.getSelectedWherePart().append(builder.toString());
  }

  private void appendGroupRedundancyCondition(String redundancyingAttrMetaPath) {
    
    
    String redundancyingTableAlias =
        this.findTableAlias(redundancyingAttrMetaPath);
    if (StringUtil.isEmptyWithTrim(redundancyingTableAlias)) {
    
    
      return;
    }
    IAttribute redundancyingAttr =
        this.getMainBean().getAttributeByPath(redundancyingAttrMetaPath);
    String column = redundancyingAttr.getColumn().getName();
    if (this.isAppendCurrentGroup()) {
    
    
      SqlBuilder builder = new SqlBuilder();
      builder.append(" and ");
      String pk_group = AppContext.getInstance().getPkGroup();
      builder.append(redundancyingTableAlias + "." + column, pk_group);
      this.getSelectedWherePart().append(builder.toString());
    }
  }

  private void appendGroupWhere() {
    
    
    String mainAlias = this.getMainTableAlias();
    String groupColumnName = this.getGroupColumnName();
    SqlBuilder builder = new SqlBuilder();
    String pk_group = AppContext.getInstance().getPkGroup();
    builder.append(mainAlias + "." + groupColumnName, pk_group);
    this.getAddedWherePart().append(" and ");
    this.getAddedWherePart().append(builder.toString());
  }

  private void appendMainDrWhere() {
    
    
    String mainAlias = this.getMainTableAlias();
    if (!StringUtil.isEmptyWithTrim(this.getSelectedWherePart().toString())) {
    
    
      this.getSelectedWherePart().append(" and ");
    }
    SqlBuilder builder = new SqlBuilder();
    builder.append(mainAlias + ".dr", 0);
    this.getSelectedWherePart().append(builder.toString());
  }

  private void appendMainTable() {
    
    
    this.getMainFromPart().append(this.getMainTableAlias());
    this.getMainFromPart().append(" ");
    this.getMainFromPart().append(this.getMainTableAlias());
    this.getMainFromPart().append(" ");
  }

  private void appendPowerSql() {
    
    
    Boolean powerEnable =
        (Boolean) this.queryScheme.get(QueryConstants.KEY_POWERENABLE);
    // 是否启用了权限,默认为启用
    if (powerEnable != null && !powerEnable.booleanValue()) {
    
    
      return;
    }
    PowerSqlUtils powerSqlUtils = new PowerSqlUtils(this.getMainBean());
    String powerSql = powerSqlUtils.generatePowerSql(new ITableAliasGetter() {
    
    

      @Override
      public String getTableAlias(IAttribute atttibute) {
    
    
        String metaPath =
            NonMetaQuerySchemeProcessor.this.findMetaPathByAttr(atttibute,
                NonMetaQuerySchemeProcessor.this.getAttributeMap());
        return NonMetaQuerySchemeProcessor.this
            .getTableAliasOfAttribute(metaPath);
      }
    });
    this.getSelectedWherePart().append(powerSql);
  }

  private void appendRedundancyCondition(String redundancyedAttrMetaPath,
      String redundancyingAttrMetaPath) {
    
    
    String redundancyingTableAlias =
        this.findTableAlias(redundancyingAttrMetaPath);
    if (StringUtil.isEmptyWithTrim(redundancyingTableAlias)) {
    
    
      return;
    }
    if (this.getGroupColumnName().equals(redundancyedAttrMetaPath)) {
    
    
      this.appendGroupRedundancyCondition(redundancyingAttrMetaPath);
    }
    String fieldCode = null;
    Set<Entry<String, String>> entrySet = this.columnMapping.entrySet();
    for (Entry<String, String> entry : entrySet) {
    
    
      if (redundancyedAttrMetaPath.equals(entry.getValue())) {
    
    
        fieldCode = entry.getKey();
        break;
      }
    }
    if (fieldCode == null) {
    
    
      return;
    }
    IFilter filter = this.getRedundancyedFilter(fieldCode);
    if (filter == null) {
    
    
      return;
    }
    String baseSql = filter.getBasicSql();
    IAttribute redundancyingAttr =
        this.getMainBean().getAttributeByPath(redundancyingAttrMetaPath);
    String redundancyingColumn = redundancyingAttr.getColumn().getName();
    StringBuffer redundancySql = new StringBuffer();
    if (baseSql.contains(fieldCode)) {
    
    
      redundancySql.append(baseSql.replace(fieldCode, redundancyingTableAlias
          + NonMetaQuerySchemeProcessor.DOT_SIGN + redundancyingColumn));
    }
    else {
    
    
      ExceptionUtils.unSupported();
    }

    this.getSelectedWherePart().append(" and " + redundancySql);
  }

  /**
   * 拼接在查询对话框上用户已选的条件
   */
  private void appendSelectCondition() {
    
    
    IFilter[] filters =
        (IFilter[]) this.queryScheme.get(IQueryScheme.KEY_FILTERS);
    for (IFilter filter : filters) {
    
    
      if (this.isCondition(filter)) {
    
    
        this.appendSelectedWhere(filter);
      }
    }
  }

  private void appendSelectedWhere(IFilter filter) {
    
    
    String fieldCode = filter.getFilterMeta().getFieldCode();
    String metaPath = this.columnMapping.get(fieldCode);
    String origSql = filter.getBasicSql();
    if (StringUtil.isEmptyWithTrim(origSql)) {
    
    
      return;
    }
    // 主要是适配这种情况的:业务组在做非元数据查询模板的时候可能为了方便,关联了一个假的元数据
    // 这样就导致了平台在那边处理的时候拼接单个条件的sql片段时候按照元数据的方式处理了,不是完全根据
    // field code来拼接的,而是用列名拼接的
    if (fieldCode.contains(".") && !origSql.contains(".")) {
    
    
      String[] names = fieldCode.split("\\.");
      origSql = origSql.replace(names[names.length - 1], fieldCode);
    }
    String tableAlias = this.getTableAliasOfFieldCode(fieldCode);
    IAttribute attribute = this.getMainBean().getAttributeByPath(metaPath);
    String columnOfAttr = attribute.getColumn().getName();
    String newFieldCode =
        tableAlias + NonMetaQuerySchemeProcessor.DOT_SIGN + columnOfAttr;
    if (!StringUtil.isEmptyWithTrim(this.getSelectedWherePart().toString())) {
    
    
      this.getSelectedWherePart().append(" and ");
    }
    this.getSelectedWherePart()
        .append(origSql.replace(fieldCode, newFieldCode));

  }

  private void constructFixPart() {
    
    
    if (!this.isNeedAppendFixPart()) {
    
    
      return;
    }
    this.getQuerySchemeSqlInfo().setNeedAppendFixPart(false);
    this.appendMainTable();
    if (this.isAppendCurrentGroup()) {
    
    
      this.appendGroupWhere();
    }
    this.appendSelectCondition();
    this.appendMainDrWhere();
    this.appendChildrenDrWhere();
    this.appendPowerSql();
    this.processRedundancyConditions();
  }

  private String fetchTableAliasByAliasPath(String aliasPath) {
    
    
    return this.getAlias_map().get(aliasPath);
  }

  private String findTableAlias(String attrMetaPath) {
    
    
    int lastDotIndex =
        attrMetaPath.lastIndexOf(NonMetaQuerySchemeProcessor.DOT_SIGN);
    String tableAlias = null;
    if (lastDotIndex < 0) {
    
    
      tableAlias = this.getMainTableAlias();
    }
    else {
    
    
      IAttribute attribute =
          this.getMainBean().getAttributeByPath(attrMetaPath);
      String tableOfAttr = attribute.getTable().getName();
      String aliasPath;
      if (!QuerySchemeUtils.isAttrOwnToExpandTable(this.getMainBean(),
          attrMetaPath)) {
    
    
        aliasPath = attrMetaPath.substring(0, lastDotIndex);
      }
      else {
    
    
        aliasPath = attrMetaPath.substring(0, lastDotIndex) + "." + tableOfAttr;
      }
      tableAlias = this.fetchTableAliasByAliasPath(aliasPath);
    }
    return tableAlias;
  }

  private String generateAlias(String tableName) {
    
    
    if (this.getAlias_map() != null
        && this.getAlias_map().containsValue(tableName)) {
    
    
      return this.generateAlias(tableName + "1");
    }
    return tableName;
  }

  private String generateInnerJoinSql(String parentAlias, String table,
      String parentLinkColumn, String linkColumn, String aliasPath) {
    
    
    String tablieAlias = this.generateAlias(table);
    StringBuffer sql = new StringBuffer();
    sql.append(" inner join ");
    sql.append(table).append(" ").append(tablieAlias);
    sql.append(" on ");
    sql.append(tablieAlias).append(".").append(linkColumn);
    sql.append(" = ");
    sql.append(parentAlias).append(".").append(parentLinkColumn);
    this.getAlias_map().put(aliasPath, tablieAlias);
    return sql.toString();
  }

  private StringBuffer getAddedFromPart() {
    
    
    // return this.addedFromPart;
    return this.getQuerySchemeSqlInfo().getAddedFromPart();
  }

  private StringBuffer getAddedWherePart() {
    
    
    // return this.addedWherePart;
    return this.getQuerySchemeSqlInfo().getAddedWherePart();
  }

  private Map<String, String> getAlias_map() {
    
    
    // return this.alias_map;
    return this.getQuerySchemeSqlInfo().getTable_alias_map();
  }

  private Map<String, IAttribute> getAttributeMap(IBean bean, String collPath) {
    
    
    List<IAttribute> attrs = bean.getAttributes();
    Map<String, IAttribute> dataPowerAttrs = new HashMap<String, IAttribute>();
    for (IAttribute attr : attrs) {
    
    
      if (MDUtil.isCollectionType(attr.getDataType())) {
    
    // 分析聚合的子表实体
        ICollectionType ctype = (ICollectionType) attr.getDataType();
        IBean childBean = (IBean) ctype.getElementType();
        dataPowerAttrs.putAll(this.getAttributeMap(childBean,
            (collPath != null ? collPath + "." : "") + attr.getName()));
      }
      else {
    
    
        dataPowerAttrs.put(
            (collPath != null ? collPath + "." : "") + attr.getName(), attr);
      }
    }
    return dataPowerAttrs;
  }

  private String getGroupColumnName() {
    
    
    return QuerySchemeUtils.getGroupColumnName(this.getMainBean());
  }

  private IBean getMainBean() {
    
    
    if (this.mainBean == null) {
    
    
      try {
    
    
        this.mainBean =
            MDBaseQueryFacade.getInstance().getBeanByFullClassName(
                this.mainEntityClass.getName());
      }
      catch (MetaDataException e) {
    
    
        ExceptionUtils.wrappException(e);
      }
    }
    return this.mainBean;
  }

  private StringBuffer getMainFromPart() {
    
    
    // return this.mainFromPart;
    return this.getQuerySchemeSqlInfo().getMainFromPart();
  }

  private String getMainTableAlias() {
    
    
    return this.getMainBean().getTable().getName();
  }

  private String getParentPath(String metaPath) {
    
    
    int lastDotIndex =
        metaPath.lastIndexOf(NonMetaQuerySchemeProcessor.DOT_SIGN);
    String parentAttrPath;
    if (lastDotIndex < 0) {
    
    
      parentAttrPath = IQuerySQLGenerator.DEFAULT_KEY;
    }
    else {
    
    
      parentAttrPath = metaPath.substring(0, lastDotIndex);
    }
    return parentAttrPath;
  }

  private ITable getParentTableByPath(String parentAttrPath) {
    
    
    ITable parentTable;
    if (IQuerySQLGenerator.DEFAULT_KEY.equals(parentAttrPath)) {
    
    
      parentTable = this.getMainBean().getTable();
    }
    else {
    
    
      IAttribute parentAttr =
          this.getMainBean().getAttributeByPath(parentAttrPath);
      IType parentAttrType = parentAttr.getDataType();
      if (MDUtil.isCollectionType(parentAttrType)) {
    
    
        IBean parentBean =
            (IBean) ((ICollectionType) parentAttrType).getElementType();
        parentTable = parentBean.getTable();
      }
      else if (MDUtil.isRefType(parentAttrType)) {
    
    
        IBean parentBean = ((IRefType) parentAttrType).getRefType();
        parentTable = parentBean.getTable();
      }
      else {
    
    
        parentTable = parentAttr.getTable();
      }
    }
    return parentTable;
  }

  private QuerySchemeSqlInfo getQuerySchemeSqlInfo() {
    
    
    QuerySchemeSqlInfo sqlInfo =
        (QuerySchemeSqlInfo) this.queryScheme.get(QueryConstants.KEY_SQL_INFO
            + "_" + this.getMainTableAlias());
    if (sqlInfo == null) {
    
    
      sqlInfo = new QuerySchemeSqlInfo();
      this.queryScheme
          .put(QueryConstants.KEY_SQL_INFO + "_" + this.getMainTableAlias(),
              sqlInfo);
    }
    return sqlInfo;
  }

  private IFilter getRedundancyedFilter(String redundancyedAttrMetaPath) {
    
    
    IFilter[] filters =
        (IFilter[]) this.queryScheme.get(IQueryScheme.KEY_FILTERS);
    for (IFilter filter : filters) {
    
    
      if (redundancyedAttrMetaPath
          .equals(filter.getFilterMeta().getFieldCode())) {
    
    
        return filter;
      }
    }
    return null;
  }

  @SuppressWarnings("unchecked")
  private Map<String, List<String>> getRedundancyInfos() {
    
    
    Map<String, List<String>> redundancyInfos =
        (Map<String, List<String>>) this.queryScheme
            .get(QueryConstants.KEY_REDUNDANCY_INFO);
    return redundancyInfos;
  }

  private StringBuffer getSelectedFromPart() {
    
    
    // return this.selectedFromPart;
    return this.getQuerySchemeSqlInfo().getSelectedFromPart();
  }

  private StringBuffer getSelectedWherePart() {
    
    
    // return this.selectedWherePart;
    return this.getQuerySchemeSqlInfo().getSelectedWherePart();
  }

  private boolean isAppendCurrentGroup() {
    
    
    // return this.appendCurrentGroup;
    return this.getQuerySchemeSqlInfo().isAppendCurrentGroup();
  }

  private boolean isCondition(IFilter filter) {
    
    
    return this.columnMapping
        .containsKey(filter.getFilterMeta().getFieldCode());
  }

  private boolean isNeedAppendFixPart() {
    
    
    // return this.needAppendFixPart;
    return this.getQuerySchemeSqlInfo().isNeedAppendFixPart();
  }

  private void joinExpandTableForicbly(String metaPath) {
    
    
    int lastDotIndex =
        metaPath.lastIndexOf(NonMetaQuerySchemeProcessor.DOT_SIGN);
    String parentAttrPath;
    String tableName;
    // 主表字段
    if (lastDotIndex < 0) {
    
    
      parentAttrPath = IQuerySQLGenerator.DEFAULT_KEY;
      tableName = metaPath;
    }
    else {
    
    
      parentAttrPath = metaPath.substring(0, lastDotIndex);
      tableName = metaPath.substring(lastDotIndex + 1, metaPath.length());
    }
    String tableOfBeanAlias = this.fetchTableAliasByAliasPath(parentAttrPath);
    if (StringUtil.isEmptyWithTrim(tableOfBeanAlias)) {
    
    
      this.joinNormalTableForcibly(parentAttrPath);
      tableOfBeanAlias = this.fetchTableAliasByAliasPath(parentAttrPath);
    }
    String linkColumn = null;
    ITable tableOfBean = null;
    if (IQuerySQLGenerator.DEFAULT_KEY.equals(parentAttrPath)) {
    
    
      tableOfBean = this.getMainBean().getTable();
    }
    else {
    
    
      tableOfBean =
          this.getMainBean().getAttributeByPath(parentAttrPath).getTable();
    }
    linkColumn = tableOfBean.getPrimaryKeyName();
    String innerSql =
        this.generateInnerJoinSql(tableOfBeanAlias, tableName, linkColumn,
            linkColumn, parentAttrPath + "." + tableName);
    this.getSelectedFromPart().append(innerSql);
  }

  private void joinNormalTableForcibly(String metaPath) {
    
    
    String parentAttrPath = this.getParentPath(metaPath);
    String parentAlias = this.fetchTableAliasByAliasPath(parentAttrPath);
    if (StringUtil.isEmptyWithTrim(parentAlias)) {
    
    
      this.joinNormalTableForcibly(parentAttrPath);
      parentAlias = this.fetchTableAliasByAliasPath(parentAttrPath);
    }
    ITable parentTable = this.getParentTableByPath(parentAttrPath);
    IAttribute attribute = this.getMainBean().getAttributeByPath(metaPath);
    IType attrType = attribute.getDataType();
    ITable table = attribute.getTable();
    String linkColumn;
    String parentLinkColumn;
    if (MDUtil.isCollectionType(attrType)) {
    
    
      parentLinkColumn = parentTable.getPrimaryKeyName();
      linkColumn = attribute.getColumn().getName();
    }
    else if (MDUtil.isRefType(attrType)) {
    
    
      table = ((IRefType) attrType).getRefType().getTable();
      parentLinkColumn = attribute.getColumn().getName();
      linkColumn = table.getPrimaryKeyName();
    }
    else {
    
    
      table = attribute.getTable();
      parentLinkColumn = table.getPrimaryKeyName();
      linkColumn = parentLinkColumn;
    }
    String innerJoinSql =
        this.generateInnerJoinSql(parentAlias, table.getName(),
            parentLinkColumn, linkColumn, metaPath);
    this.getSelectedFromPart().append(innerJoinSql);
  }

  private void processRedundancyConditions() {
    
    
    Map<String, List<String>> redundancyInfos = this.getRedundancyInfos();
    if (redundancyInfos == null) {
    
    
      return;
    }
    Set<Entry<String, List<String>>> entrySet = redundancyInfos.entrySet();
    for (Entry<String, List<String>> entry : entrySet) {
    
    
      List<String> redundancyingAttrMetaPaths = entry.getValue();
      String redundancyedAttrMetaPath = entry.getKey();
      for (String redundancyingAttrMetaPath : redundancyingAttrMetaPaths) {
    
    
        this.appendRedundancyCondition(redundancyedAttrMetaPath,
            redundancyingAttrMetaPath);
      }
    }
  }

}

查询方案处理器(有元数据):

package nc.vo.pubapp.query2.sql.process;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import nc.bs.framework.common.NCLocator;
import nc.impl.pubapp.pattern.database.IDExQueryBuilder;
import nc.itf.uap.pf.metadata.IFlowBizItf;
import nc.jdbc.framework.util.DBConsts;
import nc.md.MDBaseQueryFacade;
import nc.md.common.AssociationKind;
import nc.md.model.IAssociation;
import nc.md.model.IAttribute;
import nc.md.model.IBean;
import nc.md.model.IBusinessEntity;
import nc.md.model.ICardinality;
import nc.md.model.ITable;
import nc.md.model.MetaDataException;
import nc.md.model.type.ICollectionType;
import nc.md.model.type.IRefType;
import nc.md.model.type.IType;
import nc.md.util.MDUtil;
import nc.pubitf.rbac.IFunctionPermissionPubService;
import nc.ui.querytemplate.filter.IFilter;
import nc.ui.querytemplate.querytree.FromWhereSQL;
import nc.ui.querytemplate.querytree.FromWhereSQLImpl;
import nc.ui.querytemplate.querytree.IQuerySQLGenerator;
import nc.ui.querytemplate.querytree.IQueryScheme;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.pf.change.PfUtilBaseTools;
import nc.vo.pub.BusinessException;
import nc.vo.pub.ISuperVO;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.pub.SqlBuilder;

import org.apache.commons.lang.StringUtils;

/**
 * 查询方案处理器
 * 主要完成以下功能:
 * <OL>
 * <li>获取别名
 * <li>拼接from部分sql
 * <li>拼接from部分代码
 * </OL>
 * 当要对sql进行加工时,业务组按照如下形式使用:
 * <p>
 * 
 * <pre>
 * QuerySchemeProcessor qrySchemeProcessor = new QuerySchemProcessor(queryScheme);
 * String alias = qrySchemeProcessor.getTableAliasOfAttribute(&quot;pu_order_b.pk_org&quot;);
 * processor.appendWhere(alias + &quot;.bislatest= 'Y'&quot;);
 * String fromWherePart = processor.getFinalFromWhere();
 * </pre>
 * 
 * @since 6.0
 * @version 2011-1-13 下午03:19:17
 * @author chenyyb
 */
public class QuerySchemeProcessor {
    
    

  private static class QuerySchemeSqlInfo implements Serializable {
    
    
    private static final long serialVersionUID = -416168480378911993L;

    private StringBuffer addedFromPart = new StringBuffer();

    private StringBuffer addedWherePart = new StringBuffer();

    private boolean appendCurrentGroup = false;

    private boolean needAppendFixPart = true;

    private StringBuffer selectedFromPart = new StringBuffer();

    private StringBuffer selectedWherePart = new StringBuffer();

    private Map<String, String> table_alias_map = new HashMap<String, String>();

    QuerySchemeSqlInfo() {
    
    
      // TODO Auto-generated constructor stub
    }

    void clearAddedFromPart() {
    
    
      this.addedFromPart = new StringBuffer();
    }

    void clearAddedWherePart() {
    
    
      this.addedWherePart = new StringBuffer();
    }

    StringBuffer getAddedFromPart() {
    
    
      return this.addedFromPart;
    }

    StringBuffer getAddedWherePart() {
    
    
      return this.addedWherePart;
    }

    StringBuffer getSelectedFromPart() {
    
    
      return this.selectedFromPart;
    }

    StringBuffer getSelectedWherePart() {
    
    
      return this.selectedWherePart;
    }

    Map<String, String> getTable_alias_map() {
    
    
      return this.table_alias_map;
    }

    boolean isAppendCurrentGroup() {
    
    
      return this.appendCurrentGroup;
    }

    boolean isNeedAppendFixPart() {
    
    
      return this.needAppendFixPart;
    }

    void setAppendCurrentGroup(boolean appendCurrentGroup) {
    
    
      this.appendCurrentGroup = appendCurrentGroup;
    }

    void setNeedAppendFixPart(boolean needAppendFixPart) {
    
    
      this.needAppendFixPart = needAppendFixPart;
    }
  }

  private static final char DOT_SIGN = '.';

  private IQueryScheme queryScheme;

  public QuerySchemeProcessor(IQueryScheme queryScheme) {
    
    
    super();
    this.queryScheme = queryScheme;
  }

  /**
   * 把当前集团拼到sql中
   */
  public void appendCurrentGroup() {
    
    
    // this.appendCurrentGroup = true;
    this.getQuerySchemeSqlInfo().setAppendCurrentGroup(true);
  }

  /**
   * 添加from部分的sql片段
   * 
   * @param fromPart
   */
  public void appendFrom(String fromPart) {
    
    
    this.getAddedFromPart().append(fromPart);
  }

  public void appendFuncPermissionOrgSql() {
    
    
    this.appendFuncPermissionOrgSql(null);
  }

  /**
   * 
   * 
   * @param orgColumnName 主组织的字段名称,如果传null会自动取IBDObject所对应的主组织字段名称
   */
  public void appendFuncPermissionOrgSql(String orgColumnName) {
    
    
    String funcode =
        (String) this.queryScheme.get(QueryConstants.KEY_FUNC_NODE);
    if (funcode == null) {
    
    
      return;
    }
    String cuserid = AppContext.getInstance().getPkUser();
    String pkGroup = AppContext.getInstance().getPkGroup();
    try {
    
    
      String[] orgs =
          NCLocator.getInstance().lookup(IFunctionPermissionPubService.class)
              .getUserPermissionPkOrgs(cuserid, funcode, pkGroup);
      String columnName =
          orgColumnName == null ? QuerySchemeUtils
              .getOrgColumnName(this.queryScheme) : orgColumnName;
      String sql = null;
      String mainAlias = this.getMainTableAlias();
      // 如果用户未分配任何组织时应该查不到任何单据
      if (orgs == null || orgs.length == 0) {
    
    
        SqlBuilder builder = new SqlBuilder();
        builder.append(mainAlias + "." + columnName, "null");
        sql = builder.toString();
      }
      else {
    
    
        // 在组织很多的时候一定要采用临时表
        // IDQueryBuilder builder = new IDQueryBuilder();
        IDExQueryBuilder builder = new IDExQueryBuilder("TEMP_PUBAPPO_");
        sql = builder.buildSQL(mainAlias + "." + columnName, orgs);
      }
      this.getAddedWherePart().append(" and ");
      this.getAddedWherePart().append(sql);
    }
    catch (BusinessException e) {
    
    
      ExceptionUtils.wrappException(e);
    }

  }

  /**
   * 根据传入的下游交易类型,找到接口关系中可生成下游的上游交易类型,将这些交易类型拼接到查询条件中。
   * <p>
   * 使用场景:
   * <ul>
   * <li>一般用于上游给下游转单查询,下游查询的节点是交易类型发布的节点
   * <li>而且走单据接口对照关系来确定上游可参照的交易类型
   * </ul>
   * 
   * @example
   *          appendRefTrantypeWhere(POBillType.PrayBill.getCode(),
   *          POBillType.Order.getCode(), PraybillHeaderVO.VTRANTYPECODE);
   * @param srcBilltypeCode 上游单据类型
   * @param destBilltypeCode 下游单据类型
   * @param srcTrantypeCodeAttPath 上游交易类型编码字段的元数据路径
   */
  public void appendRefTrantypeWhere(String srcBilltypeCode,
      String destBilltypeCode, String srcTrantypeCodeAttPath) {
    
    
    String followtrantype =
        (String) this.queryScheme.get(QueryConstants.KEY_FOLLOW_TRANSTYPE);
    if (StringUtils.isBlank(followtrantype)
        || !PfUtilBaseTools.isTranstype(followtrantype)) {
    
    
      return;
    }
    String tabAlias = this.getTableAliasOfAttribute(srcTrantypeCodeAttPath);
    int dotIndex =
        srcTrantypeCodeAttPath.lastIndexOf(QuerySchemeProcessor.DOT_SIGN);
    String trantypefd = srcTrantypeCodeAttPath;
    if (dotIndex >= 0) {
    
    
      trantypefd = srcTrantypeCodeAttPath.substring(dotIndex + 1);
    }
    this.getSelectedWherePart().append(
        this.createRefTrantypeWhere(AppContext.getInstance().getPkGroup(),
            tabAlias, trantypefd, srcBilltypeCode, destBilltypeCode,
            followtrantype));
  }

  /**
   * 添加where部分的sql片段
   * 
   * @param wherePart
   */
  public void appendWhere(String wherePart) {
    
    
    this.getAddedWherePart().append(wherePart);
  }

  /**
   * 清空之前的加工信息
   */
  public void clearAppendedSqlInfo() {
    
    
	if (this.queryScheme.get(QueryConstants.KEY_SQL_INFO) == null)
		  return;
	  
    ((QuerySchemeSqlInfo) this.queryScheme.get(QueryConstants.KEY_SQL_INFO))
        .clearAddedFromPart();
    ((QuerySchemeSqlInfo) this.queryScheme.get(QueryConstants.KEY_SQL_INFO))
        .clearAddedWherePart();
  }

  /**
   * @deprecated 废弃方法,请直接调用{@link #getFinalFromWhere()},无需调用特定的方法组装sql
   */
  @Deprecated
  public String constructFinalFromWhere() {
    
    
    this.constructFixPart();
    FromWhereSQL fromWhereSQL = this.queryScheme.getTableJoinFromWhereSQL();
    StringBuffer sql = new StringBuffer();
    sql.append(" from ");
    if (fromWhereSQL.getFrom() != null) {
    
    
      sql.append(fromWhereSQL.getFrom());
    }
    sql.append(" ");
    sql.append(this.getSelectedFromPart());
    sql.append(" ");
    sql.append(this.getAddedFromPart());
    sql.append(" where ");
    if (fromWhereSQL.getWhere() != null) {
    
    
      sql.append(fromWhereSQL.getWhere());
    }
    sql.append(" ");
    sql.append(this.getSelectedWherePart());
    sql.append(" ");
    sql.append(this.getAddedWherePart());
    return sql.toString();
  }

  /**
   * 获得加工之后最终的sql
   * 
   * @return
   */
  public String getFinalFromWhere() {
    
    
    return this.constructFinalFromWhere();
  }

  /**
   * @param fieldCode
   * @return
   * @deprecated 请调用{
    
    {@link #getQueryCondition(String)}
   */
  @Deprecated
  public QueryCondition getLogicalCondition(String fieldCode) {
    
    
    return this.getQueryCondition(fieldCode);
  }

  public String getMainTableAlias() {
    
    
    FromWhereSQL fromWhereSql = this.queryScheme.getTableJoinFromWhereSQL();
    String mainTableAlias =
        fromWhereSql.getTableAliasByAttrpath(FromWhereSQL.DEFAULT_ATTRPATH);
    if (StringUtils.isBlank(mainTableAlias)) {
    
    
      mainTableAlias =
          this.getTable_alias_map().get(FromWhereSQL.DEFAULT_ATTRPATH);
    }
    return mainTableAlias;
  }

  @SuppressWarnings("unchecked")
  public QueryCondition getQueryCondition(String fieldCode) {
    
    
    Map<String, QueryCondition> conditionMap =
        (Map<String, QueryCondition>) this.queryScheme
            .get(QueryConstants.QUERY_CONDITION);
    if (conditionMap == null) {
    
    
      return null;
    }
    return conditionMap.get(fieldCode);
  }

  /**
   * 获取字段所在表的表别名
   * 这个方法是有一些局限的,在使用的时候要注意:
   * <p>
   * <li>在获取字段引用的档案实体表别名的时候,只支持一层,即字段直接引用的实体,对于那些间接
   * 引用的档案是不支持的,比如如果我采购订单的某个字段引用了物料档案,那么我通过传入物料档案的
   * class和物料档案上的任意一个字段名称是可以获取物料表在查询sql中的别名的。但是如果想要拿到物料实体
   * 引用的物料分类实体的表的别名,这个方法是做不到的。
   * <li>如果待查的主实体、子实体、甚至是子子实体中都引用了物料档案,也别使用这个方法,
   * 因为即使你能拿到正确的别名,最终拿到的sql中的from部分的join拼接也有可能会有问题不是你所期望的。
   * 需要在上面两种情况下获取相关别名信息的,请自己组织好元数据路径作为参数直接调用
   * {@link #getTableAliasOfAttribute(String)}。
   * 尽管如此,这个方法还是能够满足各个业务组80%以上的场景,新增它的目的是消除业务组在
   * 组织元数据路径的时候一些硬编码可能给以后的代码维护带来一些问题,如果没有以上两种情况的局限 尽量调用这个方法
   * 
   * @param entityClass 字段所在实体对应的class
   * @param attrName 字段名称
   * @see #getTableAliasOfAttribute(String)
   * @return
   */
  public String getTableAliasOfAttribute(Class<? extends ISuperVO> entityClass,
      String attrName) {
    
    
    String attrMetaPath = this.getAttrMetaPath(entityClass, attrName);
    if (attrMetaPath == null) {
    
    
      throw new IllegalArgumentException("未知错误");/* -=notranslate=- */
    }
    return this.getTableAliasOfAttribute(attrMetaPath);
  }

  /**
   * 
   * 获取字段所在表的表别名,传递参数的时候传入字段的元数据路径。
   * 路径形式为bodyfk.pk_material.pk_material形式
   * 
   * @param attrMetaPath
   * @return
   */
  public String getTableAliasOfAttribute(String attrMetaPath) {
    
    
    String tableAlias = this.findTableAlias(attrMetaPath);
    String aliasPath = null;
    // 在获取别名的过程中如果没有获取到别名说明当前的sql中没有拼上该字段所在的表,
    // 要先在sql中拼上该字段所在的表并且自定义别名,并且存储在查询方案中
    if (StringUtil.isEmptyWithTrim(tableAlias)) {
    
    
      if (QuerySchemeUtils.isAttrOwnToExpandTable(this.queryScheme,
          attrMetaPath)) {
    
    
        int lastDotIndex =
            attrMetaPath.lastIndexOf(QuerySchemeProcessor.DOT_SIGN);
        String parentAttrPath = null;
        if (lastDotIndex >= 0) {
    
    
          parentAttrPath = attrMetaPath.substring(0, lastDotIndex);
        }
        IAttribute attribute =
            QuerySchemeUtils.getMainBean(this.queryScheme).getAttributeByPath(
                attrMetaPath);
        String tableName = attribute.getTable().getName();
        aliasPath =
            parentAttrPath == null ? tableName : parentAttrPath + "."
                + tableName;
        this.joinExpandTableForicbly(aliasPath);
        tableAlias = this.fetchTableAliasByAliasPath(aliasPath);
      }
      else {
    
    
        int lastDotIndex =
            attrMetaPath.lastIndexOf(QuerySchemeProcessor.DOT_SIGN);
        if (lastDotIndex < 0) {
    
    
          throw new RuntimeException("系统错误");/* -=notranslate=- */
        }
        aliasPath = attrMetaPath.substring(0, lastDotIndex);
        this.joinNormalTableForcibly(aliasPath);
        tableAlias = this.fetchTableAliasByAliasPath(aliasPath);
      }
    }
    return tableAlias;
  }

  /**
   * 拼子表的dr字段
   */
  private void appendChildrenDrWhere() {
    
    
    IBean mainBean = QuerySchemeUtils.getMainBean(this.queryScheme);
    List<IAssociation> associations =
        mainBean.getAssociationsByKind(AssociationKind.Composite,
            ICardinality.ASS_ALL);
    if (associations == null) {
    
    
      return;
    }
    SqlBuilder builder = new SqlBuilder();
    for (IAssociation association : associations) {
    
    
      if (association == null) {
    
    
        continue;
      }
      String startAttr = association.getStartAttribute().getName();
      IBusinessEntity endBean = (IBusinessEntity) association.getEndBean();
      String keyAttr = endBean.getKeyAttribute().getName();
      String aliasPath = startAttr + QuerySchemeProcessor.DOT_SIGN + keyAttr;
      String childAlias = this.findTableAlias(aliasPath);
      // 只有在子表有条件的之后才会拼dr=0条件
      if (StringUtil.isEmptyWithTrim(childAlias)) {
    
    
        continue;
      }
      builder.append(" and ");
      builder.append(childAlias + ".dr", 0);
    }
    this.getSelectedWherePart().append(builder.toString());
  }

  /**
   * 拼固定的交易类型sql,节点可能是交易类型发布的节点,所以要在sql中把固定的交易类型拼接上
   */
  private void appendFixTranstype() {
    
    
    String transtype =
        (String) this.queryScheme.get(QueryConstants.KEY_TRANSTYPE);
    if (StringUtils.isBlank(transtype)) {
    
    
      return;
    }
    IBean mainBean = QuerySchemeUtils.getMainBean(this.queryScheme);
    Map<String, String> bizInterfaceMapInfo =
        ((IBusinessEntity) mainBean).getBizInterfaceMapInfo(IFlowBizItf.class
            .getName());
    if (bizInterfaceMapInfo == null) {
    
    
      return;
    }
    String pk_trantypeAttrName =
        bizInterfaceMapInfo.get(IFlowBizItf.ATTRIBUTE_TRANSTYPEPK);
    if (pk_trantypeAttrName == null) {
    
    
      return;
    }
    if (QuerySchemeUtils.hasCondition(pk_trantypeAttrName, this.queryScheme)) {
    
    
      return;
    }
    IAttribute attribute = mainBean.getAttributeByName(pk_trantypeAttrName);
    String pk_trantypeColName = attribute.getColumn().getName();
    String mainAlias = this.getMainTableAlias();
    SqlBuilder builder = new SqlBuilder();
    builder.append(mainAlias + "." + pk_trantypeColName, transtype);
    this.getAddedWherePart().append(" and ");
    this.getAddedWherePart().append(builder.toString());
  }

  /**
   * 拼接冗余字段
   * 
   * @param redundancyingAttrMetaPath
   */
  private void appendGroupRedundancyCondition(String redundancyingAttrMetaPath) {
    
    
    String redundancyingTableAlias =
        this.findTableAlias(redundancyingAttrMetaPath);
    if (StringUtil.isEmptyWithTrim(redundancyingTableAlias)) {
    
    
      return;
    }
    IBean mainBean = QuerySchemeUtils.getMainBean(this.queryScheme);
    IAttribute redundancyingAttr =
        mainBean.getAttributeByPath(redundancyingAttrMetaPath);
    String column = redundancyingAttr.getColumn().getName();
    // if (this.appendCurrentGroup) {
    
    
    if (this.isAppendCurrentGroup()) {
    
    
      SqlBuilder builder = new SqlBuilder();
      builder.append(" and ");
      String pk_group = AppContext.getInstance().getPkGroup();
      builder.append(redundancyingTableAlias + "." + column, pk_group);
      this.appendRedundancyWherePart(builder.toString());
    }
  }

  /**
   * 拼接默认集团
   */
  private void appendGroupWhere() {
    
    
    String mainAlias = this.getMainTableAlias();
    String groupColumnName = this.getGroupColumnName();
    SqlBuilder builder = new SqlBuilder();
    // String pk_group = InvocationInfoProxy.getInstance().getGroupId();
    String pk_group = AppContext.getInstance().getPkGroup();
    builder.append(mainAlias + "." + groupColumnName, pk_group);
    this.getAddedWherePart().append(" and ");
    this.getAddedWherePart().append(builder.toString());
  }

  /**
   * 拼主表的dr字段
   */
  private void appendMainDrWhere() {
    
    
    String mainAlias = this.getMainTableAlias();
    FromWhereSQLImpl fromWhereSQL =
        (FromWhereSQLImpl) this.queryScheme.getTableJoinFromWhereSQL();
    String where = fromWhereSQL.getWhere();
    SqlBuilder builder = new SqlBuilder();
    if (!StringUtil.isEmptyWithTrim(where)) {
    
    
      builder.append(" and ");
    }
    builder.append(mainAlias + ".dr", 0);
    this.getSelectedWherePart().append(builder.toString());
  }

  private void appendRedundancyCondition(String redundancyedAttrMetaPath,
      String redundancyingAttrMetaPath) {
    
    
    String mainTableAlias = this.getMainTableAlias();
    String redundancyingTableAlias =
        this.findTableAlias(redundancyingAttrMetaPath);
    if (StringUtil.isEmptyWithTrim(redundancyingTableAlias)) {
    
    
      return;
    }
    if (this.getGroupColumnName().equals(redundancyedAttrMetaPath)) {
    
    
      this.appendGroupRedundancyCondition(redundancyingAttrMetaPath);
    }
    IFilter filter = this.getRedundancyedFilter(redundancyedAttrMetaPath);
    if (filter == null) {
    
    
      return;
    }
    String baseSql = filter.getBasicSql();
    if (baseSql == null) {
    
    
      return;
    }
    IBean mainBean = QuerySchemeUtils.getMainBean(this.queryScheme);
    IAttribute redundancyingAttr =
        mainBean.getAttributeByPath(redundancyingAttrMetaPath);
    String redundancyingColumn = redundancyingAttr.getColumn().getName();
    StringBuffer redundancySql = new StringBuffer();
    if (baseSql.contains(mainTableAlias + QuerySchemeProcessor.DOT_SIGN)) {
    
    
      redundancySql.append(baseSql.replace(mainTableAlias
          + QuerySchemeProcessor.DOT_SIGN, redundancyingTableAlias
          + QuerySchemeProcessor.DOT_SIGN));
    }
    else {
    
    
      int firstColumnIndex = baseSql.indexOf(redundancyingColumn);
      redundancySql.append(baseSql);
      if (firstColumnIndex != -1) {
    
    
        redundancySql.insert(firstColumnIndex, redundancyingTableAlias
            + QuerySchemeProcessor.DOT_SIGN);
      }
      // 一个字段可能对应两个值,比如单据日期,当操作符是介于的时候就有两个日期
      int lastColumnIndex = baseSql.lastIndexOf(redundancyingColumn);
      // 如果两个索引不一致的话这个字段就对应两个值
      if (lastColumnIndex != firstColumnIndex) {
    
    
        // 在插入子表的别名之后字符的位置发生了变化,所以要重新取位置
        int newLastColumnIndex = redundancySql.lastIndexOf(redundancyingColumn);
        redundancySql.insert(newLastColumnIndex, redundancyingTableAlias
            + QuerySchemeProcessor.DOT_SIGN);
      }
    }

    this.appendRedundancyWherePart(" and " + redundancySql);
  }

  private void appendRedundancyWherePart(String wherePart) {
    
    
    this.getSelectedWherePart().append(wherePart);
  }

  private void constructFixPart() {
    
    
    if (!this.isNeedAppendFixPart()) {
    
    
      return;
    }
    this.getQuerySchemeSqlInfo().setNeedAppendFixPart(false);
    this.appendMainDrWhere();
    if (this.isAppendCurrentGroup()) {
    
    
      this.appendGroupWhere();
    }
    // 处理冗余字段
    this.processRedundancyConditions();
    this.appendChildrenDrWhere();
    this.appendFixTranstype();
  }

  public SqlBuilder createRefTrantypeWhere(String pk_group, String tabAlias,
      String trantypeFdName, String srcBilltypeCode, String destBilltypeCode,
      String destTrantypeCode) {
    
    
    SqlBuilder sql = new SqlBuilder();
    sql.append(" and ");
    sql.append("( ");
    sql.append("    exists ");
    sql.append("    ( ");
    sql.append("        select ");
    sql.append("            1 ");
    sql.append("        from ");
    sql.append("            pub_billitfdef itfdef ");
    sql.append("        where ");
    sql.append("            itfdef.pk_group", pk_group);
    sql.append("        and itfdef.src_billtype", srcBilltypeCode);
    sql.append("        and itfdef.dest_billtype", destBilltypeCode);
    sql.append("        and itfdef.dest_transtype", destTrantypeCode);
    sql.append("        and itfdef.src_transtype=" + tabAlias + "."
        + trantypeFdName + ") ");
    sql.append("    or ");
    sql.append("    exists ");
    sql.append("    ( ");
    sql.append("        select ");
    sql.append("            1 ");
    sql.append("        from ");
    sql.append("            pub_billitfdef itfdef ");
    sql.append("        where ");
    sql.append("            itfdef.pk_group", pk_group);
    sql.append("        and itfdef.src_billtype", srcBilltypeCode);
    sql.append("        and itfdef.dest_billtype", destBilltypeCode);
    sql.append("        and itfdef.dest_transtype", destTrantypeCode);
    sql.appendIDIsNull("        and isnull(itfdef.src_transtype,'"
        + DBConsts.NULL_WAVE + "')");
    sql.append(")) ");
    sql.append("and ");
    sql.append("not exists ");
    sql.append("( ");
    sql.append("    select ");
    sql.append("        1 ");
    sql.append("    from ");
    sql.append("        pub_billitfdef itfdef ");
    sql.append("    where ");
    sql.append("            itfdef.pk_group", pk_group);
    sql.append("        and itfdef.src_billtype", srcBilltypeCode);
    sql.append("        and itfdef.dest_billtype", destBilltypeCode);
    sql.append("    and itfdef.dest_transtype<>'" + destTrantypeCode + "' ");
    sql.append("        and itfdef.src_transtype=" + tabAlias + "."
        + trantypeFdName + ") ");
    return sql;
  }

  private String fetchTableAliasByAliasPath(String aliasPath) {
    
    
    FromWhereSQL fromWhereSQL = this.queryScheme.getTableJoinFromWhereSQL();
    String tableAlias = fromWhereSQL.getTableAliasByAttrpath(aliasPath);
    if (StringUtil.isEmptyWithTrim(tableAlias)) {
    
    
      tableAlias = this.getTable_alias_map().get(aliasPath);
    }
    return tableAlias;
  }

  private String findTableAlias(String attrMetaPath) {
    
    
    int lastDotIndex = attrMetaPath.lastIndexOf(QuerySchemeProcessor.DOT_SIGN);
    String tableAlias = null;
    FromWhereSQL fromWhereSQL = this.queryScheme.getTableJoinFromWhereSQL();
    if (lastDotIndex < 0) {
    
    
      if (!QuerySchemeUtils.isAttrOwnToExpandTable(this.queryScheme,
          attrMetaPath)) {
    
    
        tableAlias =
            fromWhereSQL
                .getTableAliasByAttrpath(IQuerySQLGenerator.DEFAULT_KEY);
      }
      else {
    
    
        IAttribute attribute =
            QuerySchemeUtils.getMainBean(this.queryScheme).getAttributeByPath(
                attrMetaPath);
        String tableName = attribute.getTable().getName();
        tableAlias = fromWhereSQL.getTableAliasByAttrpath(tableName);
      }
    }
    else {
    
    
      IAttribute attribute =
          QuerySchemeUtils.getMainBean(this.queryScheme).getAttributeByPath(
              attrMetaPath);
      String tableOfAttr = attribute.getTable().getName();
      String aliasPath;
      if (!QuerySchemeUtils.isAttrOwnToExpandTable(this.queryScheme,
          attrMetaPath)) {
    
    
        aliasPath = attrMetaPath.substring(0, lastDotIndex);
      }
      else {
    
    
        aliasPath = attrMetaPath.substring(0, lastDotIndex) + "." + tableOfAttr;
      }
      tableAlias = this.fetchTableAliasByAliasPath(aliasPath);
    }
    return tableAlias;
  }

  private String generateAlias(String tableName) {
    
    
    FromWhereSQLImpl fromWhereSql =
        (FromWhereSQLImpl) this.queryScheme.getTableJoinFromWhereSQL();
    Map<String, String> alias_map = fromWhereSql.getAttrpath_alias_map();
    if (alias_map != null && alias_map.containsValue(tableName)) {
    
    
      return this.generateAlias(tableName + "1");
    }
    alias_map = this.getTable_alias_map();
    if (alias_map != null && alias_map.containsValue(tableName)) {
    
    
      return this.generateAlias(tableName + "1");
    }
    return tableName;
  }

  private String generateInnerJoinSql(String parentAlias, String table,
      String parentLinkColumn, String linkColumn, String aliasPath) {
    
    
    String tablieAlias = this.generateAlias(table);
    StringBuffer sql = new StringBuffer();
    sql.append(" left join ");
    sql.append(table).append(" ").append(tablieAlias);
    sql.append(" on ");
    sql.append(tablieAlias).append(".").append(linkColumn);
    sql.append(" = ");
    sql.append(parentAlias).append(".").append(parentLinkColumn);

    this.getTable_alias_map().put(aliasPath, tablieAlias);
    return sql.toString();
  }

  private StringBuffer getAddedFromPart() {
    
    
    return this.getQuerySchemeSqlInfo().getAddedFromPart();
    // return this.addedFromPart;
  }

  private StringBuffer getAddedWherePart() {
    
    
    // return this.addedWherePart;
    return this.getQuerySchemeSqlInfo().getAddedWherePart();
  }

  private String getAttrMetaPath(Class<? extends ISuperVO> entityClass,
      String attrName) {
    
    
    IBean mainBean = QuerySchemeUtils.getMainBean(this.queryScheme);
    return this.getAttrMetaPath(entityClass, attrName, mainBean);
  }

  private String getAttrMetaPath(Class<? extends ISuperVO> entityClass,
      String attrName, IBean mainBean) {
    
    
    List<IAssociation> compositeAssos =
        mainBean.getAssociationsByKind(AssociationKind.Composite,
            ICardinality.ASS_ALL);
    for (IAssociation compositeAsso : compositeAssos) {
    
    
      IAttribute startAttr = compositeAsso.getStartAttribute();
      IBean endBean = compositeAsso.getEndBean();
      String childAttrMetaPath =
          this.getAttrMetaPath(entityClass, attrName, endBean);
      if (childAttrMetaPath != null) {
    
    
        return startAttr.getName() + QuerySchemeProcessor.DOT_SIGN
            + childAttrMetaPath;
      }
    }
    List<IAssociation> associations = mainBean.getAssociations();
    try {
    
    
      IBean bean =
          MDBaseQueryFacade.getInstance().getBeanByFullClassName(
              entityClass.getName());
      //主子孙结构的单据,元数据是分主子和子孙2个,其中的子bean类路径为同一个,但bean不同,
      //因此不能使用bean本身来判断是否同一个,需判断其对应类路径
      if (bean.getFullClassName().equals(mainBean.getFullClassName())) {
    
    
        return attrName;
      }
      for (IAssociation association : associations) {
    
    
        if (bean.getFullClassName().equals(association.getEndBean().getFullClassName())) {
    
    
          IAttribute startAttr = association.getStartAttribute();
          return startAttr.getName() + QuerySchemeProcessor.DOT_SIGN + attrName;
        }
      }
    }
    catch (MetaDataException e) {
    
    
      ExceptionUtils.wrappException(e);
    }

    return null;
  }

  private String getGroupColumnName() {
    
    
    return QuerySchemeUtils.getGroupColumnName(this.queryScheme);
  }

  private String getParentPath(String metaPath) {
    
    
    int lastDotIndex = metaPath.lastIndexOf(QuerySchemeProcessor.DOT_SIGN);
    String parentAttrPath;
    if (lastDotIndex < 0) {
    
    
      parentAttrPath = IQuerySQLGenerator.DEFAULT_KEY;
    }
    else {
    
    
      parentAttrPath = metaPath.substring(0, lastDotIndex);
    }
    return parentAttrPath;
  }

  private ITable getParentTableByPath(String parentAttrPath) {
    
    
    ITable parentTable;
    if (IQuerySQLGenerator.DEFAULT_KEY.equals(parentAttrPath)) {
    
    
      parentTable = QuerySchemeUtils.getMainBean(this.queryScheme).getTable();
    }
    else {
    
    
      IAttribute parentAttr =
          QuerySchemeUtils.getMainBean(this.queryScheme).getAttributeByPath(
              parentAttrPath);
      IType parentAttrType = parentAttr.getDataType();
      if (MDUtil.isCollectionType(parentAttrType)) {
    
    
        IBean parentBean =
            (IBean) ((ICollectionType) parentAttrType).getElementType();
        parentTable = parentBean.getTable();
      }
      else if (MDUtil.isRefType(parentAttrType)) {
    
    
        IBean parentBean = ((IRefType) parentAttrType).getRefType();
        parentTable = parentBean.getTable();
      }
      else {
    
    
        parentTable = parentAttr.getTable();
      }
    }
    return parentTable;
  }

  private QuerySchemeSqlInfo getQuerySchemeSqlInfo() {
    
    
    QuerySchemeSqlInfo sqlInfo =
        (QuerySchemeSqlInfo) this.queryScheme.get(QueryConstants.KEY_SQL_INFO);
    if (sqlInfo == null) {
    
    
      sqlInfo = new QuerySchemeSqlInfo();
      this.queryScheme.put(QueryConstants.KEY_SQL_INFO, sqlInfo);
    }
    return sqlInfo;
  }

  private IFilter getRedundancyedFilter(String redundancyedAttrMetaPath) {
    
    
    IFilter[] filters =
        (IFilter[]) this.queryScheme.get(IQueryScheme.KEY_FILTERS);
    for (IFilter filter : filters) {
    
    
      if (redundancyedAttrMetaPath
          .equals(filter.getFilterMeta().getFieldCode())) {
    
    
        return filter;
      }
    }
    return null;
  }

  @SuppressWarnings("unchecked")
  private Map<String, List<String>> getRedundancyInfos() {
    
    
    Map<String, List<String>> redundancyInfos =
        (Map<String, List<String>>) this.queryScheme
            .get(QueryConstants.KEY_REDUNDANCY_INFO);
    return redundancyInfos;
  }

  private StringBuffer getSelectedFromPart() {
    
    
    // return this.selectedFromPart;
    return this.getQuerySchemeSqlInfo().getSelectedFromPart();
  }

  private StringBuffer getSelectedWherePart() {
    
    
    // return this.selectedWherePart;
    return this.getQuerySchemeSqlInfo().getSelectedWherePart();
  }

  private Map<String, String> getTable_alias_map() {
    
    
    // return this.table_alias_map;
    return this.getQuerySchemeSqlInfo().getTable_alias_map();
  }

  private boolean isAppendCurrentGroup() {
    
    
    // return this.appendCurrentGroup;
    return this.getQuerySchemeSqlInfo().isAppendCurrentGroup();
  }

  private boolean isNeedAppendFixPart() {
    
    
    // return this.needAppendFixPart;
    return this.getQuerySchemeSqlInfo().isNeedAppendFixPart();
  }

  /**
   * 给sql拼扩展表
   * 
   * @param metaPath 规范跟
   *          {@link nc.ui.querytemplate.querytree.FromWhereSQL#getTableAliasByAttrpath(String)}
   *          中的参数一样
   */
  private void joinExpandTableForicbly(String metaPath) {
    
    
    int lastDotIndex = metaPath.lastIndexOf(QuerySchemeProcessor.DOT_SIGN);
    String parentAttrPath;
    String tableName;
    if (lastDotIndex < 0) {
    
    
      parentAttrPath = IQuerySQLGenerator.DEFAULT_KEY;
      tableName = metaPath;
    }
    else {
    
    
      parentAttrPath = metaPath.substring(0, lastDotIndex);
      tableName = metaPath.substring(lastDotIndex + 1, metaPath.length());
    }
    String tableOfBeanAlias = this.fetchTableAliasByAliasPath(parentAttrPath);
    if (StringUtil.isEmptyWithTrim(tableOfBeanAlias)) {
    
    
      this.joinNormalTableForcibly(parentAttrPath);
      tableOfBeanAlias = this.fetchTableAliasByAliasPath(parentAttrPath);
    }
    String linkColumn = null;
    ITable tableOfBean = null;
    if (IQuerySQLGenerator.DEFAULT_KEY.equals(parentAttrPath)) {
    
    
      tableOfBean = QuerySchemeUtils.getMainBean(this.queryScheme).getTable();
    }
    else {
    
    
      tableOfBean =
          QuerySchemeUtils.getMainBean(this.queryScheme)
              .getAttributeByPath(parentAttrPath).getTable();
    }
    linkColumn = tableOfBean.getPrimaryKeyName();
    String innerSql =
        this.generateInnerJoinSql(tableOfBeanAlias, tableName, linkColumn,
            linkColumn,
            IQuerySQLGenerator.DEFAULT_KEY.equals(parentAttrPath) ? tableName
                : parentAttrPath + "." + tableName);
    this.getSelectedFromPart().append(innerSql);
  }

  /**
   * 给sql拼上必须表(非扩展表)
   * 
   * @param metaPath 规范跟
   *          {@link nc.ui.querytemplate.querytree.FromWhereSQL#getTableAliasByAttrpath(String)}
   *          中的参数一样
   */
  private void joinNormalTableForcibly(String metaPath) {
    
    
    // 主表的话直接拼上主表
    if (IQuerySQLGenerator.DEFAULT_KEY.equals(metaPath)) {
    
    
      IBean bean = QuerySchemeUtils.getMainBean(this.queryScheme);
      String mainTableName = bean.getTable().getName();
      this.getSelectedFromPart().append(mainTableName);
      this.getTable_alias_map().put(IQuerySQLGenerator.DEFAULT_KEY,
          mainTableName);
      return;
    }
    String parentAttrPath = this.getParentPath(metaPath);
    String parentAlias = this.fetchTableAliasByAliasPath(parentAttrPath);
    if (StringUtil.isEmptyWithTrim(parentAlias)) {
    
    
      this.joinNormalTableForcibly(parentAttrPath);
      parentAlias = this.fetchTableAliasByAliasPath(parentAttrPath);
    }
    ITable parentTable = this.getParentTableByPath(parentAttrPath);
    IAttribute attribute =
        QuerySchemeUtils.getMainBean(this.queryScheme).getAttributeByPath(
            metaPath);
    IType attrType = attribute.getDataType();
    ITable table = attribute.getTable();
    String linkColumn;
    String parentLinkColumn;
    if (MDUtil.isCollectionType(attrType)) {
    
    
      parentLinkColumn = parentTable.getPrimaryKeyName();
      linkColumn = attribute.getColumn().getName();
    }
    else if (MDUtil.isRefType(attrType)) {
    
    
      table = ((IRefType) attrType).getRefType().getTable();
      parentLinkColumn = attribute.getColumn().getName();
      linkColumn = table.getPrimaryKeyName();
    }
    else {
    
    
      table = attribute.getTable();
      parentLinkColumn = table.getPrimaryKeyName();
      linkColumn = parentLinkColumn;
    }
    String innerJoinSql =
        this.generateInnerJoinSql(parentAlias, table.getName(),
            parentLinkColumn, linkColumn, metaPath);
    this.getSelectedFromPart().append(innerJoinSql);
  }

  private void processRedundancyConditions() {
    
    
    Map<String, List<String>> redundancyInfos = this.getRedundancyInfos();
    if (redundancyInfos == null) {
    
    
      return;
    }
    Set<Entry<String, List<String>>> entrySet = redundancyInfos.entrySet();
    for (Entry<String, List<String>> entry : entrySet) {
    
    
      List<String> redundancyingAttrMetaPaths = entry.getValue();
      String redundancyedAttrMetaPath = entry.getKey();
      for (String redundancyingAttrMetaPath : redundancyingAttrMetaPaths) {
    
    
        this.appendRedundancyCondition(redundancyedAttrMetaPath,
            redundancyingAttrMetaPath);
      }
    }
  }

}

猜你喜欢

转载自blog.csdn.net/u010741112/article/details/129982588