OAF中多语言转换开发实现步骤 一文介绍了OAF多语言转换开发的步骤。
但也产生了如下的疑问:
- 程序怎么知道需要不需要进行多语言转换?
- 页面中也没有TL表相关的视图对象,它的多语言数据又怎么进去?
- 在OAF开发中,需要往数据库插入数据,都是通过EO的操作来实现,但是按照开发手册,我们是基于VL视图来创建EO,复合式视图又无法插入数据,这是怎么回事?
- 而多语言转换的基表根本就没有定义EO,它是什么时候插入数据的?
带着上面的疑问,我们来看看实体对象的实现类OAEntityImpl是如何来实现多语言转换功能的
一、首先来看看EO的create方法
public void create(AttributeList paramAttributeList)
{
super.create(paramAttributeList);
createRowWho();
createObjectVersionNumber();
if (isTranslatable())
createTranslated(paramAttributeList);
}
其中isTranslatable()来判读是否需要多语言的转化,如果需要就调用createTranslated()方法,否则就按照默认的创建方式调用父类的create方法
isTrnaslattable()方法最终是通过getBaseTableName()方法来判断是否需要实现多语言转换:
private String getBaseTableName()
{
return ((String)getEntityDef().getProperty("OA_BASE_TABLE"));
}
getBaseTableName()方法取得实体对象的自定义实体属性OA_BASE_TABLE,这个属性就是开发时定义在VL视图的实体对象上面的,所以只要设置了这个属性,就会被认为需要进行多语言的转换
上面回答了我的第一个疑问:程序如何知道多语言转换
二、看看专门为多语言转换所设计的createTranslated()方法
private RowIterator createTranslated(AttributeList paramAttributeList)
{
RowIterator localRowIterator = getTLEOIterator();
String str = getOADBTransaction().getCurrentLanguage();
String[] arrayOfString2 = getInstalledLanguages();
int j = getTLLanguageAttributeIndex();
int k = getTLSourceLangAttributeIndex();
for (int l = 0; l < arrayOfString2.length; ++l)
{
RowImpl localRowImpl = (RowImpl)localRowIterator.createRow();
localRowImpl.setAttribute(j, arrayOfString2[l]);
localRowImpl.setAttribute(k, str);
localRowIterator.insertRow(localRowImpl);
}
return localRowIterator;
}
getTLEOIterator()方法则是返回TL对应的EO行集实例,看到代码中的一个for循环,循环是基于目前已安装的语言进行的,因此当往VL视图实体对象中插入数据的时候,就会按照已安装的语言往TL表中插入记录
这里回答了:如何插入TL表的数据,而且还了解了为什么一次可以将所有语言环境的信息都插入到TL表中。
另外关于如何找到VL实体对象对应的TL实体对象就留个读者自己去完成吧(OATranslatedEntityStaticInfo类中)
但是这里并没有看到数据往多语言基表插入的程序,让我们继续浏览代码。
三、查看生成DML语句的buildDMLStatement方法
protected StringBuffer buildDMLStatement(int paramInt, AttributeDefImpl[] paramArrayOfAttributeDefImpl1, AttributeDefImpl[] paramArrayOfAttributeDefImpl2, AttributeDefImpl[] paramArrayOfAttributeDefImpl3, boolean paramBoolean)
{
if (!(isTranslatable()))
return super.buildDMLStatement(paramInt, paramArrayOfAttributeDefImpl1, paramArrayOfAttributeDefImpl2, paramArrayOfAttributeDefImpl3, paramBoolean);
StringBuffer localStringBuffer = super.buildDMLStatement(paramInt, trimXlatAttributes(paramArrayOfAttributeDefImpl1), trimXlatAttributes(paramArrayOfAttributeDefImpl2), trimXlatAttributes(paramArrayOfAttributeDefImpl3), paramBoolean);
if (localStringBuffer == null)
return null;
String str = localStringBuffer.toString();
str = OACommonUtils.replace(str, getEntityDef().getSource(), getBaseTableName());
return new StringBuffer(str);
}
其中最关键的一句是OACommonUtils.replace(str, getEntityDef().getSource(), getBaseTableName()); ,这个语句将本来是VL视图的名字getEntityDef().getSource()替换为多语言基表的名字getBaseTableName(),
这样看似是往VL实体对象中插入数据,而实际上已经被偷梁换柱了。它根本就不会往VL视图对象上面进行DML操作。
这样一来我们首先提出的3,4疑问都已经得到回答:为什么可以操作视图和TL的多语言基表的数据是怎么被插入的?
但是细心的人会发现新的问题了。上面的buildDMLStatement方法中,难道仅仅将DML语句中的表对象更换了就可以了吗?
答案是否定的,因为VL的数据库列和多语言基表是不一样的,基于VL实体对象中的列属性比基表多了多语言的那些字段。
四、查看多语言属性剔除方法trimXlatAttributes
从代码中注意到buildDMLStatement方法调用了trimXlatAttributes()方法来处理了传入的参数,让我们看看trimXlatAttributes()方法的实现
private AttributeDefImpl[] trimXlatAttributes(AttributeDefImpl[] paramArrayOfAttributeDefImpl)
{
if (paramArrayOfAttributeDefImpl == null)
return null;
int i = 0;
for (int j = 0; j < paramArrayOfAttributeDefImpl.length; ++j)
if (!(isTranslatableAttribute(j)))
++i;
AttributeDefImpl[] arrayOfAttributeDefImpl = new AttributeDefImpl[i];
int k = 0;
for (int l = 0; l < paramArrayOfAttributeDefImpl.length; ++l)
if (!(isTranslatableAttribute(l)))
{
arrayOfAttributeDefImpl[k] = paramArrayOfAttributeDefImpl[l];
++k;
}
return arrayOfAttributeDefImpl;
}
代码中有isTranslatableAttribute()方法来判断相应的列是否为多语言转换的列,如果不是则添加到arrayOfAttributeDefImpl[]数组,否则丢弃。
这样处理之后返回的数据就只包括了除去多语言属性的列,这刚好是多语言基表中的属性列,所以上面buildDMLStatement()方法中将数据表替换为多语言基表才不会出现问题。
至此多语言实现处理的主要逻辑都已经解释完成了,另外有很多细节上面的处理就留个感兴趣的人去研究吧。