# 产品区隔组件

# 开场问题

V8.1版本有A6+、A8+、A8-N、G6+、G6-N、G6-SU这么多产品线,其中A8+还有企业版和集团版之分,A8-N/G6+/G6-N/G6-SU还有同义的单组织和多组织之分。

这里提出两个开场问题:

  1. 这么多产品线,我们在代码中是如何版本管理的?
  2. 这么多产品线,肯定有功能的区隔(比如A6+和A8+都有致信功能,产品设计上要求致信在不同产品线上显示不同的图标,这个应该如何实现才利于维护?)

基于上面两个问题,V5提供了ProductEditionEnum和SysFlag的实现来解决问题。

# 版本定义文件ProductEditionEnum

com.seeyon.ctp.common.constants.ProductEditionEnum是版本定义文件,基本代码实现如下:

public enum ProductEditionEnum {
    a6              (0, "A6V5-1", "edition.a6.product", ""), // A6+版
    enterprise      (1, "A8V5-1", "edition.enterprise.product", ""), // A8+企业版
    entgroup        (2, "A8V5-2", "edition.entgroup.product", ""), // A8+企业集团版
    government      (3, "G6V5-1", "edition.government.product", ".GOV"), // 政务版
    governmentgroup (4, "G6V5-2", "edition.governmentgroup.product", ".GOV"), // 政务多组织版
    a8n1            (14, "A8NV5-1", "edition.a8n1.product", ""), // A8-N企业版
    a8n2            (15, "A8NV5-2", "edition.a8n2.product", ""), // A8-N企业集团版
    g6n1            (16, "G6NV5-1", "edition.g6n1.product", ".GOV"), // G6-N单组织版
    g6n2            (17, "G6NV5-2", "edition.g6n2.product", ".GOV"),// G6-N多组织版
 g6su1           (18, "G6SUV5-1", "edition.governmentsupervision.product", ".GOV"), // G6-督查督办单组织版
 g6su2           (19, "G6SUV5-2", "edition.governmentsupervisiongroup.product", ".GOV") // G6-督查督办多组织版
    ;
......
}

我们可以通过ProductEditionEnum.getCurrentProductEditionEnum()方法获取到当前正在使用的协同产品线:

int productId = ProductEditionEnum.getCurrentProductEditionEnum().key;

那么,你可能还有个问题:系统是怎么知道我当前正在使用的产品线的?

我们对产品线进行了多重描述:产品线定义文件+产品描述文件+数据库标记+加密狗文件。以后在开发分析问题的时候,可以通过如下方式去了解客户产品线

产品线定义文件存放于:ApacheJetspeed\webapps\seeyon\common\js\ui\publicinfomenu.js

产品描述文件存放于:ApacheJetspeed\webapps\seeyon\WEB-INF\cfgHome\base\productFeature.xml

# 功能区隔组件SysFlag

那么回到开场问题:比如A6+和A8+都有致信功能,产品设计上要求致信在不同产品线上显示不同的图标,这个应该如何实现才利于维护?

那么,我们开发可能会考虑基于currentProductEdition就能用来做功能区隔:

int currentProductId= ProductEditionEnum.getCurrentProductEditionEnum().getKey();
if(currentProductId == ProductEditionEnum.a6.getKey()) {

}else {

}

可以明确的是:上面这段代码在当前版本是有效的。但是如果下个版本又出现了b6+、c6+的产品线,同样需要做屏蔽怎么办?

如果我们代码中有几十上百处都这样来处理,那么下个版本就要修改几十上百处的代码,对代码的可维护性太差!

基于可维护的问题,平台提供了SysFlag工具类。

# SysFlag的用法

倒过来介绍,先介绍如果在SysFlag中定义了必要的方法之后,我们会怎么改写上面的代码:

boolean ucEnabled = (boolean) SysFlag.ucEnableButton.getFlag();

上面这一句简单代码即可实现enable功能,SysFlag.ucEnableButton的实现代码如下:

public enum SysFlag {

    /***************************************************************************
     * 开发人员定义的代码在这里 参数顺序依次是:A6-s-V5, A6-V5, A8企业版标志、A8企业集团版、政务版标志、政务多组织版、UFIDA-NC套件版标志、cwork
     */
    sys_isGroupVer(false, false, false, true, false, true, true, false), //是否为多组织版本
    sys_isEnterpriseVer(false, false, true, false, false, false, false, false), //是否为企业版本
    sys_isGovVer(false, false, false, false, true, true, false, false), //是否为政务版本(含政务版和政务多组织版)
    sys_isA6Ver(true, true, false, false, false, false, false, false), //是否为A6
    sys_isG6S(false, false, false, false, false, false, false, false), //是否为G6-s
    ucEnableButton(false, false, true, true, true, true, true, true), // 致信屏蔽A6+特性
}

上面代码的释义:枚举下面每个参数代表一个产品线,第二个参数代表A6+,第三个代表A8企业版,第四个代表A8集团版,通过不同参数true、false控制就能来确定什么产品线支持什么功能。

综上,如果要基于产品线屏蔽某个功能特性,开发只需要在SysFlag下面新增一个枚举,针对对应产品线设置标识语句即可。

当然,如果需要不同产品线使用不同的图标,还可以直接在SysFlag中定义图标文件名,在代码中直接调用即可:

IconSuffix("abouta6.png", "abouta81.png", "abouta82.png", "default.png", "default.png", "default.png", "default.png", "default.png")

# SysFlag的实现原理

SysFlag的实现原理很简单:就是初始化的时候就内置了当前产品线,随后在调用SysFlag枚举的时候已经能定位到对应枚举变量了,代码如下:

public enum SysFlag {

    /***************************************************************************
     * 开发人员定义的代码在这里 参数顺序依次是:A6-s-V5, A6-V5, A8企业版标志、A8企业集团版、政务版标志、政务多组织版、UFIDA-NC套件版标志、cwork
     */

    ucEnableButton(false, false, true, true, true, true, true, true), // 致信屏蔽A6+特性

    ;

    private Map<ProductEditionEnum, Object> flags = new EnumMap<ProductEditionEnum, Object>(ProductEditionEnum.class);

    SysFlag(Object a6sFlag, Object a6Flag, Object enterpriseFlag, Object entgroupFlag, Object governmentFlag, Object governmentgroupFlag, Object ufidancFlag, Object cworkFlag) {
        flags.put(ProductEditionEnum.a6s, a6sFlag);
        flags.put(ProductEditionEnum.a6, a6Flag);
        flags.put(ProductEditionEnum.a6p, a6Flag);
        flags.put(ProductEditionEnum.enterprise, enterpriseFlag);
        flags.put(ProductEditionEnum.a8n1, enterpriseFlag);
        flags.put(ProductEditionEnum.entgroup, entgroupFlag);
        flags.put(ProductEditionEnum.a8n2, entgroupFlag);
        flags.put(ProductEditionEnum.government, governmentFlag);
        flags.put(ProductEditionEnum.governmentgroup, governmentgroupFlag);
        flags.put(ProductEditionEnum.ufidanc, ufidancFlag);
        flags.put(ProductEditionEnum.cwork, cworkFlag);
        flags.put(ProductEditionEnum.g6n1, governmentFlag);
        flags.put(ProductEditionEnum.g6n2, governmentgroupFlag);
        flags.put(ProductEditionEnum.g6su1, governmentFlag);
        flags.put(ProductEditionEnum.g6su2, governmentgroupFlag);
    }

    /**
     * 取得标志,自动识别版本
     * 
     * @return 对应版本的标志
     */
    public Object getFlag() {
        return flags.get(currentProductEdition);
    }

    //产品版本.
    private static ProductEditionEnum currentProductEdition = null;

    static{
        currentProductEdition = ProductEditionEnum.getCurrentProductEditionEnum();
    }

}
创建人:het