public List<?> copyParam(Long paramId, Long toParamId) {
    Param copyParam = paramDao.getEntity(paramId);
    Param toParam = paramDao.getEntity(toParamId);

    Long copyParamId = copyParam.getId();
    List<?> params = paramDao.getChildrenById(copyParamId);
    Map<Long, Long> paramMapping = new HashMap<Long, Long>(); // 复制出来的新节点 与 被复制源节点 建立一一对应关系(ID 对 ID)
    for (int i = 0; i < params.size(); i++) {
      Param param = (Param) params.get(i);
      Long sourceParamId = param.getId();

      paramDao.evict(param);
      param.setId(null);
      if (sourceParamId.compareTo(copyParamId) == 0) {
        param.setParentId(toParam.getId());
        param.setSeqNo(paramDao.getNextSeqNo(toParam.getId()));
      } else {
        param.setParentId(paramMapping.get(param.getParentId()));
      }

      // 如果目标根节点是停用状态,则所有新复制出来的节点也一律为停用状态
      param.setDisabled(toParam.getDisabled());

      judgeLegit(param, ParamConstants.EDIT_FLAG);

      paramDao.create(param);
      paramMapping.put(sourceParamId, param.getId());
    }
    return params;
  }
  public List<?> copyParam(Long paramId, Long toParamId) {
    Param param = paramDao.getEntity(paramId);

    if (null == toParamId) {
      return copyParamLocal(param);
    } else {
      return copyParamTo(param, paramDao.getEntity(toParamId));
    }
  }
  /**
   * 字段重复判断。 (区分参数组、参数、参数项的概念) 不同参数的code不可以相同,必须帮助每个参数 的code值对整个参数表中的“参数”唯一
   *
   * @param param
   */
  private void judgeLegit(Param param, int flag) {
    // 如果保存的是参数(区分参数组、参数、参数项的概念),则要保证code值对所有“参数”唯一
    Integer type = param.getType();
    if (ParamConstants.NORMAL_PARAM_TYPE.equals(type)) {
      String hql = "select p.id from Param p where p.type = ? and p.code = ?";
      List<?> list = paramDao.getEntities(hql, ParamConstants.NORMAL_PARAM_TYPE, param.getCode());
      if (list.size() > flag) {
        throw new BusinessException("相同参数名称(指CODE)已经存在,请更改参数名称后再保存!");
      }
      return;
    }

    String hql = "select p.id from Param p where p.parentId=" + param.getParentId();
    if (ParamConstants.GROUP_PARAM_TYPE.equals(type)) { // 参数组不能同名
      hql += " and p.name='" + param.getName() + "'";
    } else {
      Param parentParam = paramDao.getEntity(param.getParentId());
      param.setModality(parentParam.getModality());
      hql += " and p.text='" + param.getText() + "' ";
    }

    if (paramDao.getEntities(hql).size() > flag) {
      throw new BusinessException("参数已存在,不要重复创建! checked by : " + hql);
    }
  }
  /**
   * 字段重复判断。 (区分参数组、参数、参数项的概念) 不同参数的code不可以相同,必须帮助每个参数 的code值对整个参数表中的“参数”唯一
   *
   * @param param
   */
  private void judgeLegit(Param param, int flag) {
    // 如果保存的是参数(区分参数组、参数、参数项的概念),则要保证code值对所有“参数”唯一
    Integer type = param.getType();
    if (ParamConstants.NORMAL_PARAM_TYPE.equals(type)) {
      String hql = "select p.id from Param p where p.type = ? and p.code = ?";
      List<?> list =
          paramDao.getEntities(
              hql, new Object[] {ParamConstants.NORMAL_PARAM_TYPE, param.getCode()});
      if (list.size() > flag) {
        throw new BusinessException("相同参数名称(指CODE)已经存在,请更改参数名称后再保存!");
      }
      return;
    }

    String hql = "select p.id from Param p where p.parentId=" + param.getParentId();
    if (ParamConstants.GROUP_PARAM_TYPE.equals(param.getType())) { // 参数组不能同名
      hql += " and p.name='" + param.getName() + "'";
    } else if (ParamConstants.NORMAL_PARAM_TYPE.equals(param.getType())) {
      if (EasyUtils.isNullOrEmpty(param.getName())) {
        param.setName(param.getCode());
      }
      hql += " and (p.name='" + param.getName() + "' or p.code='" + param.getCode() + "')";
    } else {
      if (EasyUtils.isNullOrEmpty(param.getText())) {
        param.setText(param.getValue());
      }
      Param parentParam = paramDao.getEntity(param.getParentId());
      param.setModality(parentParam.getModality());
      hql += " and (p.value='" + param.getValue() + "' or p.text='" + param.getText() + "')";
    }

    if (paramDao.getEntities(hql).size() > flag) {
      throw new BusinessException("字段重复! + " + hql);
    }
  }
  public void delete(Long id) {
    checkPermission(id);

    // 一并删除子节点
    List<?> children = paramDao.getChildrenById(id);
    for (Object entity : children) {
      Param item = (Param) entity;
      if (id.equals(item.getId())) {
        fireListener(item); /* 在执行delete前触发触发器,否则执行如getParentsById等查询时,因o1已经删除,将查询不到数据 */
        item = paramDao.getEntity(id);
      }
      paramDao.delete(item);
    }
  }
  public void move(Long paramId, Long toParamId) {
    List<?> params = paramDao.getChildrenById(paramId);
    for (int i = 0; i < params.size(); i++) {
      Param param = (Param) params.get(i);
      if (param.getId().equals(paramId)) { // 判断是否是移动节点(即被移动枝的根节点)
        param.setSeqNo(paramDao.getNextSeqNo(toParamId));
        param.setParentId(toParamId);
      }

      // 如果目标根节点是停用状态,则所有新复制出来的节点也一律为停用状态
      if (toParamId.longValue() > 0) { // 非_root
        Param toParam = paramDao.getEntity(toParamId);
        param.setDisabled(toParam.getDisabled());
      }

      paramDao.update(param);
    }
  }
  public void move(Long paramId, Long toParamId) {
    List<?> params = paramDao.getChildrenById(paramId);
    Param toParam = paramDao.getEntity(toParamId);
    for (int i = 0; i < params.size(); i++) {
      Param param = (Param) params.get(i);
      if (param.getId().equals(paramId)) { // 判断是否是移动节点(即被移动枝的根节点)
        param.setSeqNo(paramDao.getNextSeqNo(toParamId));
        param.setParentId(toParamId);
      }

      if (ParamConstants.TRUE.equals(toParam.getDisabled())) {
        param.setDisabled(ParamConstants.TRUE); // 如果目标根节点是停用状态,则所有新复制出来的节点也一律为停用状态
      }

      judgeLegit(param, ParamConstants.EDIT_FLAG);
      paramDao.update(param);
    }
  }
  public Param saveParam(Param param) {
    if (null == param.getId()) {
      param.setSeqNo(paramDao.getNextSeqNo(param.getParentId()));
      judgeLegit(param, ParamConstants.SAVE_FLAG);
      paramDao.create(param);
    } else {
      judgeLegit(param, ParamConstants.EDIT_FLAG);
      if (param.getLockVersion() == 0) { // 非param.htm维护系统参数的情况
        Param old = paramDao.getEntity(param.getId());
        param.setLockVersion(old.getLockVersion());
        param.setCreateTime(old.getCreateTime());
        param.setCreatorId(old.getCreatorId());
        param.setCreatorName(old.getCreatorName());
      }
      paramDao.update(param);
    }

    fireListener(param);

    return param;
  }
 public Param getParam(Long id) {
   Param param = paramDao.getEntity(id);
   paramDao.evict(param);
   return param;
 }