使用 NVelocity 解析 PowerDesigner 的cdm文件

使用 NVelocity 解析 PowerDesigner 的cdm文件

使用powerdesign来进行数据库设计应该是设计者的首选了,而且现在的powerdesign做得越来越好,新版的11已经开始可以把实体和需求一一对应了。powerdesign本身还能够支持数据库的创建和修改,如果oom的话也可以生成代码,并且其本身可以支持在cdm,oom,pdm格式之间的相互转换。但是在实际应用中,远远不够。因为很多程序员自己做了很多的架构和规范,powerdesign内置的单一功能的代码生成已经远远不能满足实际使用中的需求。比如想用 hibernate/NHibernate 的朋友们想直接生成 .hbm.xml 文件的话,常规方法只能够是先创建数据库,然后用hbm自己的工具反向生成代码。实际使用中,常常因为实体间多对多的关系,hbm生成的配置文件还要进行修改之后才能使用。

本人也在实际工作中遇到了同样的问题,所以把以前的几个工具综合起来,最终采用了NVelocity(http://sourceforge.net/projects/nvelocity/)来做实际的代码转换工作,我自己编了一个对cdm文件的解释器,提供给NVelocity。然后NVelocity装入我们编写的模版文件,解释并生成代码。
具体NVelocity模版怎么编写,大家可以参考http://jakarta.apache.org/velocity/中的user guide(英文)。另外我提供的工程中还会有一个测试用的小模版,基本的技巧都用到了,也可以作为参考。

我export给NVelocity的入口变量是 $pdm,是一个 PDM 的实例。其中涉及到的各个类的可用成员和解释如下所示。
其中 xxxCollection 都是一个 IList 派生的类型。

另外,这里支持在 对象的 Comment 区域中加入如下格式的自定义配置信息

 comment line1
 comment line2
 
 comment line n
 [config]
 name1
= value1  //  注释
 
 nameN
= valueN  //  注释 N


从 $pdm 中可以引用到如下的对象:

class  PDM     //  系统的总入口,对应一个pdm文件的所有内容
    NamespaceCollection Namespaces     //  pdm中所有的Package
    EntityCollection Entities          //  pdm中所有的Entity,
    DomainCollection Domains           //  pdm中所有的Domain
    DataItemCollection DataItems       //  pdm中所有的DataItem
     string  CreatePDMName( string  name,  int  count)     //  为了方便生成 pdm 的重复名字生成逻辑(属性级),
                                      
//  比如 GroupId,Gro_GroupId,Gro_GroupId1等等
     string  CreateUniqueName( string  name,  int  count)  //  为了方便生成类一级的重复名字
    
class  Namespace  //  对应一个 Package 
    EntityCollection Entities         //  该Package中的所有Entity
    DataItemCollection DataItems      //  该 Package中的所有 DataItem
    RelationshipCollection Relationships      //  该Package中的所有Relationship
    InheritanceCollection Inheritances   //  所有 Package 中的继承关系
     string  Id            //  Package 的 id
     string  ObjectId      //  Package 的 GUID
     string  Name          //  中文名称,以下所有的 Name 都是相同含义
     string  Code          //  代码名称,
    PDM Owner            //  对 PDM 的反向引用
    Comment Comment      //  Comment内容中"[config]"标志之前的内容
     string  GetConfigValue( string  name)     //  从配置中获取name对应的value,如果不存在则返回空字符串(String.Empty)
    
class  Entity     //  实体
    AttributeCollection Attributes   //  实体中所有的字段
    Index PrimaryIndex               //  主索引
    IndexCollection Indexs           //  其他索引
    DataItemCollection DataItems     //  实体中引用到的 DataItem,应该看作字段类型而不是字段
    RelationLinkCollection Relation  //  本实体需要关注的RelationLink,是经过处理了的Relationship
    RelationLinkCollection AllRelationships  //  和本实体相关的所有的 Relationship
    InheritanceCollection Base   //  所有实体相关的基类继承关系
    InheritanceCollection Derives   //  所有实体相关的派生类继承关系
     bool  Generated   //  是否要处理
     string  Id         //  同上类
     string  ObjectId 
    
string  Name 
    
string  Code 
    Namespace Owner 
    Comment Comment  
//  Comment内容中"[config]"标志之前的内容
     string  GetConfigValue( string  name)     //  从配置中获取name对应的value,如果不存在则返回空字符串(String.Empty)
    ArrayList GetBaseList()  //  获取所有的基类实体列表
    ArrayList GetDeriveList()  //  获取本实体所有的派生类实体列表
    
class  DataItem         //  数据项
     string  Id          //  同上类
     string  ObjectId 
    
string  Name 
    
string  Code 
    
int  Length   //  数据项的长度
    DataTypeInfo DataType  //  数据的类型,比如 VA50,I 等等
    Domain Domain          //  数据类型相关的 Domain 
    Namespace Owner 
    Comment Comment 
    
string  GetConfigValue( string  name)
    
class  Attribute         //  Entity 的字段
     string  Name
    
string  Code
    DataTypeInfo DataType    
    
bool  CodeExistInBase  //  相同代码的Attribute是否存在于所属实体的基类中
     bool  CodeExistInDerives  //  相同代码的Attribute是否存在于所属实体的派生类中
    DataItem DataItem
    IndexCollection Indexs 
//  Attribute 参与的索引集合
    Entity Owner 
    
string  Id 
    
string  ObjectId 
    
bool  Mandatory      //  是否必须字段
    Comment Comment     //  Comment内容中"[config]"标志之前的内容
     string  GetConfigValue( string  name)  //  从配置中获取name对应的value,如果不存在则返回空字符串(String.Empty)
    
class  Relationship     //  关系
    Entity Object1    
    Entity Object2
    RelationshipEntity RelationEntity 
//  为了方便生成中间表,特意把多对多关系的内容提到这里
                                      
//  请使用 Pd_NameExt/Pd_NameExts 来获取中间表的字段名
     string  Id 
    
string  ObjectId 
    
string  Name 
    
string  Code 
    
string  DominantRole      //  主导方,=A表示Object2要引用Object1,
                            
//  =B则反之,为""则表示都需要,已经处理在 RelationLink 中了,不需要再自行处理
     string  DependentRole     //  依赖于哪一方,A表示Object1引用Object2,B反之,为""则都需要
                            
//  同样已经处理在 RelationLink 中了,不需要自行处理
    Namespace Owner 
    Comment Comment         
//  Comment内容中"[config]"标志之前的内容
     string  GetConfigValue( string  name)     //  从配置中获取name对应的value,如果不存在则返回空字符串(String.Empty)

class  RelationLink     //  经过处理之后的关系,包含在 Entity.Relation 中,是单方关系
    Relationship Relationship      //  相关的Relationship
    Entity Owner   //  关系的拥有者
    Entity Entity    //  关系引用的 Entity
     string  Role      //  关系的名称
    Cardinality Cardinality   //  所属Entity和本关系引用的Entity之间的对应关系 1:1,1:n等等
    Cardinality ReverseCardinality      //  本关系引用的Entity和所属Entity之间的对应关系 1:1,1:n等等
     bool  IsMultiMulti    //  本关系是否多对多关系
    RelationLink Pair    //  如果是成对的关系,则指向关系的另一头
     string  Pd_Name       //  powerdesign生成的数据库字段名,如引用的Entity有复合主键,则应用Pd_Names
                        
//  如果是多对多关系的话,本名字保持原始引用名,需要用生成名请参考Pd_NameExt,
     string [] Pd_Names    //  复合主键对应的名称
     string  UniqueCode    //  为了方便处理而生成的实体中唯一的对象名称
     int  UniqueSeed   //  生成UniqueCode和Pd_Name时候使用的count参数
     string  GetConfigValue( string  name)

class  RelationshipEntity  //  多对多关系的中间实体
    Relationship Owner    //  所属的关系
     string  Name 
    
string  Code 
    RelationLinkCollection Fields 
//  实体包含的所有内容
     string  GetConfigValue( string  name)  //  获取相关的relationship中的配置信息
    
class  Cardinality     //  对应关系,比如 1:n
     string  Min        //  
     string  Max
    
class  Index         //  索引
    AttributeCollection Attributes      //  索引包含的字段
    Entity Owner 
    
string  Id 
    
string  ObjectId 
    
string  Name 
    
string  Code 
    Comment Comment    
//  注释
     string  GetConfigValue( string  name)     //  获取配置值

class  Inheritance  //  继承关系描述
    Entity Parent  //  继承关系中的基类实体
    EntityCollection Children  //  继承关系中的派生类实体
     bool  InheritAll  //  是否继承基类中所有内容
     bool  MutuallyExclusive  //  对应pd中同名参数
    Comment Comment   //  关系的注释说明
    Namespace Owner   //  关系所属的命名空间
     string  Id   //  
     string  ObjectId   //  
     string  Name   //  
     string  Code   //  
     string  GetConfigValue( string  name)  //  获取关系中的配置参数

class  Comment       //  注释
     string  Text     //  注释的全文本,包含回车换行符
     string [] Lines  //  注释的分行文本,不含回车换行符
    
class  Domain     //  Domain,对应 SQL SERVER 中的 User Type 类型
     string  Id 
    
string  ObjectId 
    
string  Name 
    
string  Code 
    DataTypeInfo DataType 
    
int  Length        //  数据类型的长度
     string  LowValue   //  取值定义的下限
     string  HighValue  //  取值定义的上限
     string  DefaultValue    //  默认值
    ValuePair[] ValueList  //  合法值列表,类似于 enum
    Comment Comment   //  注释
     string  GetConfigValue( string  name)     //  获取配置值
    
class  ValuePair       //  Domain 中合法值的信息,类似于enum
     string  Value      //  值
     string  Caption    //  值的名字
    
class  DataTypeInfo 
    
string  Type   //  把DataType中的类似 VA50 中的长度之前的类型,比如 VA
     int  Length    //  数据类型的长度

class  Helper
    
string  Char( int  ascii)  //  把 ascii 字符变换为对应的字符
     int  Ascii( string  ch)  //  获取字符的ascii码
     string  UpCase( string  text)  //  大写字符串
     string  LowerCase( string  text)  //  小写字符串
     string  Trim( string  text)  //  消除字符串前后空白字符
     bool  IsBlankString( string  text)  //  判断是否空白字符串
     string [] Split( string  text,  string  splitters)  //  切割字符串,splitters中所有字符作为切割标记



目前经过改进,已经可以支持xml格式的脚本,定义请参考代码中的xsd文件,也支持visual studio 2003工程文件属性中的custom tool,只要运行一下regist.bat,就支持名字为PDMGenerator的自定义工具在编译时进行文件的转换工作。

工程代码请到http://files.cnblogs.com/BigTall/pd-map.zip 。

在使用中会出现 NVelocity 的bug:
1。模版文件中的中文不能输出
2。在 #set($var = "this is 'my \"$baby\"' lover!") 对于连续的引号中的引号处理不正确。

-----------------
2005-5-16 更新
    1。给所有的Entity,DataItem,Domain,Attribute,Relationship都加上配置功能
    2。修正DataType的类型从string到DataTypeInfo
    3。增加RelationshipEntity的实现
    4。修正UniqueCode的实现算法

2005-5-31 更新
    1。加入inheritance的支持
    2。加入支持新的xml格式的脚本文件,以及支持代码库文件
    3。支持Visual Studio 2003的custom tool功能,使用PDMGenerate的名字就可以支持编译时转换
    4。增加$Helper输出符号,支持简单字符串处理功能,同时规避NVelocity已知错误
   

你可能感兴趣的:(powerDesigner)