OAF中多语言转换开发实现解析
十二月 6, 2008 in Oracle EBS二次开发
Oracle EBS 12.0.0
OAF中多语言转换开发实现步骤 一文介绍了OAF多语言转换开发的步骤。
但也产生了如下的疑问:
- 程序怎么知道需要不需要进行多语言转换?
- 页面中也没有TL表相关的视图对象,它的多语言数据又怎么进去?
- 在OAF开发中,需要往数据库插入数据,都是通过EO的操作来实现,但是按照开发手册,我们是基于VL视图来创建EO,复合式视图又无法插入数据,这是怎么回事?
- 而多语言转换的基表根本就没有定义EO,它是什么时候插入数据的?
带着上面的疑问,我们来看看实体对象的实现类OAEntityImpl是如何来实现多语言转换功能的
一、首先来看看EO的create方法
1 2 3 4 5 6 7 8 | public void create(AttributeList paramAttributeList) { super.create(paramAttributeList); createRowWho(); createObjectVersionNumber(); if (isTranslatable()) createTranslated(paramAttributeList); } |
其中isTranslatable()来判读是否需要多语言的转化,如果需要就调用createTranslated()方法,否则就按照默认的创建方式调用父类的create方法
isTrnaslattable()方法最终是通过getBaseTableName()方法来判断是否需要实现多语言转换:
1 2 3 4 | private String getBaseTableName() { return ((String)getEntityDef().getProperty("OA_BASE_TABLE")); } |
getBaseTableName()方法取得实体对象的自定义实体属性OA_BASE_TABLE,这个属性就是开发时定义在VL视图的实体对象上面的,所以只要设置了这个属性,就会被认为需要进行多语言的转换
上面回答了我的第一个疑问:程序如何知道多语言转换
二、看看专门为多语言转换所设计的createTranslated()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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方法
1 2 3 4 5 6 7 8 9 10 11 | 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()方法的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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()方法中将数据表替换为多语言基表才不会出现问题。
至此多语言实现处理的主要逻辑都已经解释完成了,另外有很多细节上面的处理就留个感兴趣的人去研究吧。
附上OAEntityImpl.class,OATranslatedEntityStaticInfo.class反编译的Java代码(仅供学习之用) : 
–
相关文章: