自动化企业软件开发的制作方法

文档序号:12270881阅读:489来源:国知局
相关申请的引用本申请要求2009年10月14日提交的美国临时专利申请第61/251,420号的优先权,所述美国临时专利申请的全文以引用的方式并入本文。
技术领域
:本发明总体上涉及用于自动化企业软件开发的方法和系统。具体来说,本发明涉及用于与图形建模方式相关的使计算机软件开发过程实现自动化的方法和系统。
背景技术
::企业越来越依赖于成熟的软件来管理其内部运作并向客户和顾客提供商品及服务。企业级软件的开发、部署、维护和更新对于企业推进几乎所有业务过程来说必不可少。传统的软件开发涉及大量的手动编码及测试。随着软件复杂性的增加,这类传统的手动方式已不切实际。企业软件应用程序通常包括上百万行计算机代码,且照惯例需要一些程序员团队并且花费几年时间来创建、测试和调试。为了使系统能实施,程序员需要面对繁琐的编码重复。这类手动方法生成的软件代码易于含有错误,并且手动测试可能无法覆盖全部可能的用户情境。最终的软件产品可能含有潜在错误,其会引起服务质量下降并造成重大经济损失。业界已出现基于模型的开发(Model-BasedDevelopment;MBD)方法,其转移了软件开发过程中的注意力。软件应用程序过程中的建模在编码之前发生。模型用作软件开发的蓝图。精心建构的模型可有助于负责软件开发项目的人员在执行代码之前就能完全确保以下事宜:业务功能性完整且正确,终端用户的需要得到满足,且程序设计支持可扩充性、健壮性、安全性、扩展性和其他特性的要求。如果在实际设计之后再执行代码,那么通常情况下这时候的更改是困难并且昂贵的。MBD允许在模型级别进行软件规范的验证,并且减少了手动编码量。建模工具还能使设计可视化,并将其与设计要求进行比较。统一建模语言(UnifiedModelingLanguage;UML)是可视化、说明、建构并建档软件密集型系统的制品的图形语言。UML提供标准方式来编写系统蓝图,包括诸如业务过程和系统功能的概念性事务,以及诸如编程语言语句、数据库模式和可再用软件组件的实质性事务。表1列出了标准UML元素列表。表1标准UML元素自动代码生成(Automaticcodegeneration;ACG)方法(不是应用程序生成),也已经开始在企业软件开发过程中得到应用。ACG使得工程师能够关注于高级别的设计问题,同时更好地理解业务过程。ACG可使得企业软件更快地投放市场,但不能牵动整个应用程序以及其所有的可能部分,诸如,带有处理组件的接口和数据组件。ACG过程通常包括自动代码生成器,其读取设计模式的元数据的特定集合,并以指定编程语言生成软件代码。自动代码生成器还可用于捕获企业软件应用程序的知识和业务规则,并在很短时间内以任何所要计算机语言针对任何平台生成上百万行代码。ACG过程使得企业开发项目更灵活。实施时的更改可视为同一元数据的不同渲染。源代码的一部分一旦生成,程序员就随后自由地填入代码生成器留下的间隙,并专注于系统的重要部分。这样一来,借助于代码生成过程,开发速度得以加快且可靠性得以增强。面向服务的架构(ServiceOrientedArchitecture;SOA)是一种用于根据通用式互连和相互依赖的基础块的集合建构复杂的软件密集型系统的架构方式。SOA用于根据软件服务构建应用程序。服务是功能性的内在并无关联的单元,这些单元并不调用嵌入于其内的另一服务。这些软件服务通常实施人们将认为是服务的功能性,诸如,填入帐户的在线应用程序,或是检查在线银行报表。不同于具有在源代码中相互调用的嵌入式调用的服务,SOA定义了描述一个或更多个服务如何相互通信的协议。需要一个灵活的标准化架构来更好地支持多个应用程序之间的连接以及数据共享。SOA借助于将大型应用程序结构化成调用服务的小型模块的自组织(adhoc)集合来统一业务过程。公司内部及外部的不同分组的人可使用这些应用程序,且借助于混合全局池的这些服务而构建成的新应用程序表现出灵活性和一致性。对于联营公司来说,从统一服务池构建所有应用程序,更易于达成这个目标并且部署起来更容易。这个架构可有助于企业在条件更改方面更快速地响应且更具成本效益,同时这个架构还促进宏观层面的服务等级的重复使用,但并不针对微观类层面。具有以下流线型企业软件开发工具是有利的,并且也正是所需要的,这类流线型企业软件开发工具并入有上述这些传统方法的部分,从而提供图形建模和设计工具,使大多数或全部编码实现自动化,并且这类工具具有可重复使用的组件和服务的框架,其促进定制企业应用程序的生成。目前还没有用于自动产生用来设计、生成并集成可执行应用程序的所有元素的软件应用程序的已知程序。举例来说,有些产品可以针对可执行应用程序创建设计草图,但并不随后创建设计中指定的元素,诸如,用户接口、持久性(数据库设计、数据存储和数据传输)和处理步骤。本发明实现与在一个系统中设计、生成、集成和产生相关的所要需要,而这个需要在现有系统中还没有提供过。技术实现要素:因此,本发明的一个目的是提供这类工具。为了实现上述和其他目的,本发明提出一种用于生成软件应用程序的方法,其包括以下步骤:在图形设计工具中对业务过程建模;使用表示所建模的业务过程的一个或更多个状态图以及表示数据模型并表示应用到所描述业务过程的预定的业务规则的一个或更多个类图,来创建至少一个UML模型,以形式化所描述的过程;通过使用预定的语法来检测语法错误,验证至少一个UML模型,以验证至少一个状态图或类图或其组合;以及将至少一个经验证的UML模型变换成用来生成软件应用程序的功能性和非功能性方面的元数据。在本发明的一个方面,变换步骤包括生成软件应用程序。在本发明的另一方面,所生成的软件应用程序与先前存在的库相组合。在本发明的另一方面,所生成的软件应用程序与手动编写的代码相组合。在本发明的另一方面,元数据包括一个或更多个应用程序代码、或约束模型、或自动化文件、或文档、或其一些组合。在本发明的另一方面,所生成的应用程序包括预定义的功能性要求集合。在本发明的另一方面,所生成的应用程序包括预定义的非功能性要求集合。在本发明的另一方面,预定义的非功能性要求集合包括安全性管理、或装载平衡、或事务管理、或用户接口,或构建算法的骨架,或其一些组合。在本发明的另一方面,生成步骤包括向所生成的应用程序添加手动编写的代码。在本发明的另一方面,方法还包括借助部署工具490部署目标应用程序的步骤。本发明还提供了一种用于使用计算机系统来生成软件应用程序的方法,其包括以下步骤:(a)在计算机系统中实施的图形建模和设计工具中对业务过程建模,其中图形建模和设计工具是用于统一建模语言可视化建模工具的插件;(b)通过使用表示所建模的业务过程的一个或更多个状态图以及表示数据模型并表示应用到所建模的业务过程的预定的业务规则的一个或更多个类图,在计算机系统中创建至少一个统一建模语言模型,以形式化在步骤(a)中建模的业务过程,其中一个或更多个类图包括预定义的类和装饰,其中装饰被编组成标记值和范型,其中标记值用于借助于数字或字符向数据元素添加信息,其中范型将数据元素分类成组;(c)定义关于一个或更多个类图的属性并且与一个或更多个类形成关系;(d)通过使用预定的语法来检测语法错误,在计算机系统中验证至少一个统一建模语言模型,以验证一个或更多个状态图或一个或更多个类图或者一个或更多个状态图和一个或更多个类图的组合;以及(e)在计算机系统中将在步骤(d)中验证的至少一个统一建模语言模型变换成用来生成软件应用程序的功能性和非功能性方面的元数据。本发明还提供了一种用于使用计算机系统来生成软件应用程序的方法,其包括以下步骤:(a)在计算机系统中实施的图形建模和设计工具中对业务过程建模,其中图形建模和设计工具是用于统一建模语言可视化建模工具的插件;(b)通过使用表示所建模的业务过程的状态图以及表示数据模型并表示应用到所建模的业务过程的预定的业务规则的类图,在计算机系统中创建至少一个统一建模语言模型,以形式化在步骤(a)中建模的业务过程,其中每个类图包括预定义的类和装饰,其中装饰被编组成标记值和范型,其中标记值用于借助于数字或字符向数据元素添加信息,其中范型将数据元素分类成组;(c)经由接口定义关于一个或更多个类图的属性并且与每个预定义的形成关系,其中宏类对类图中的至少一个属性的重复进行优化;(d)通过使用预定的语法来检测语法错误,在计算机系统中验证至少一个统一建模语言模型,以验证状态图或者类图或状态图和类图的组合;以及(e)生成软件应用程序,使得通过将经验证的统一建模语言模型变换成源代码、将经变换的代码与先前存在的库和配置文件相组合,能够将软件应用程序部署到服务器。附图说明下文将参照附图来描述优选实施例,附图中:图1是示例性计算环境的示意图;图2是示例性网络环境的示意图;图3是多层客户端-服务器环境的示意图;图4是使用优选实施例来开发企业软件的总体过程的流程图;图5是示例性PalmyraUMLDesignerFile菜单;图6是示例性PalmyraUMLDesigner提供附加菜单选项;图7A是Enumeration类的示例;图7B是TypeName类的示例;图7C是DynamicTypeName类的示例;图7D是Attribute类的示例;图7E是Controller类的示例;图7F是ActionEnumeration类的示例;图8是Constrainable类的示例;图9A是Entity类的示例;图9B是Composite类的示例;图9C是Macro类的示例;图9D是Controller类的示例;图10是含有ValueInterface、AbstractValueInterface、StorageInterface、HistoricizedInterface的接口类和这些接口的层次结构;图11展示寄存在案例“UCAgency”中的动作处理器“AgencyCommandSearch;图12A是示例性Palmyra类图,其演示案例图向导;图12B是具有3个步骤的示例性Palmyra案例图向导;图13A示出使用Palmyra生成工具创建新应用程序;图13B示出使用Palmyra生成工具的生成选项;图13C示出屏幕Services,其用来添加、编辑或去除服务,按钮“BuildServices”应用选定Ear文件中的修改;图13D示出使用Palmyra生成工具的配置选项;图14示出自动生成过程的主要步骤;图15A示出1对1关系的示例;图15B示出1对N关系的示例;图16示出带有接口的关系的示例;图17示出继承性的实例的示例;图18示出MenuEditorTool的用户接口的示例;图19示出Palmyra登录屏幕的示例性屏幕;图20示出实体授权过程的示例;图21示出服务授权过程的示例;图22A示出示例性SecurityItemUMLModel;图22B示出示例性PoliciesUMLModel;图22C示出示例性SecurityItem的RolesUMLModeL;图23示出ViewFormatService(视图格式服务)的UML模型的示例;图24A示出根据优选实施例的应用程序如何集成并与不同平台通信的示例;图24B以抽象方式示出系统的架构以及输入和输出装置从何处装配到这个系统中;图25示出Mapping过程的概况;图26示出Mapping的配置的示例;图27详细示出Mapping转化器的过程;图28示出工作流引擎的示例以及其如何管理系统中的状态;图29示出ReportWriter(报告编写器)的总体架构;图30示出包com.palmyra.arch.basicStruct.data的接口Value中定义的主要方法;图31示出包com.palmyra.arch.basicStruct.data中实施的类Collection;图32示出Classe的组合;图33示出com.palmyra.archbasicStruct.exception提供的异常;图34A示出CompositeValue类的子类;图34B示出StringValue类的子类;图35示出创建并定义CompositeValue类字段的示例;图36示出SimpleValue类型及其子类的类图的示例;图37A是查找操作中的查询类的UML图的图示,其中所查询类是X,且所查询字段是+、i1.+、i1.i2.+和i3.+;图37B是查找操作中的查询类的简化UML图的图示,其中所查询类是X,且所查询字段是+、i1.+、i1.i2.+和i3.+;图38是搜索查询的UML图的图示;图39是另一搜索查询的UML图的图示;图40是已扩展键结构的UML类图的图示;图41A是PQL查询的UML类图的图示;图41B是简化PQL查询的UML类图的图示;图41C是1对N关系的UML类图的图示;图42是ProcessExecuter(过程执行器)的设计模型的UML图的图示;图43是Traverser(遍历器)的设计模型的UML图的图示;以及图44是Mapper(映射器)的设计模型的示例性UML图的图示;图45是特定于供应商的DBDS子类的设计模型的示例性UML图的图示;图46是如何使用接口historicized的示例性UML图的图示;图47A是如何在设计应用程序时使用安排器模块的示例性UML图的图示;图47B是作业消息配置的示例性屏幕;图47C是如何配置每日重复的作业的示例性屏幕;图47D是如何在每日重新的作业中配置一天中的时间的示例性屏幕;图47E是如何向日历分配年度假日的示例性屏幕;图47F是如何向日历分配特殊假日的示例性屏幕;图47G是如何向日历分配每周的假日的示例性屏幕;图47H是如何在作业与日历之间定义依赖性的示例性屏幕;图47I是如何配置待跟踪作业的示例性屏幕;图47J是作业安排器的跟踪执行结果的示例性屏幕;图48示出可支持许多技术的呈现控制器的设计;图49示出经由呈现控制器和相关联组件来响应客户端请求的示例性过程;图50示出基于上下文获取动作;图51示出安排器的UML表示;以及图52示出PalmyraScheduleTrace(Palmyra安排器跟踪)的示例。具体实施方式下文将参照附图详细描述优选实施例,其中全部附图中的相同附图标记表示相同元件或步骤。示例性计算环境图1和以下论述旨在提供适合计算环境的简要总体描述,其中可在所述计算环境中实施本发明的示例实施例。然而,应了解,与优选实施例有关的使用涵盖任何种类的手持式、便携式和其他计算装置。尽管下文描述了通用计算机,但是这仅作为一个示例。优选实施例还可在具有网络服务器互操作性和交互的瘦客户端上运作。因此,本发明的示例实施例可在牵涉极少或最少客户端资源的网络宿主服务的环境中实施,例如,在客户端装置仅用作连至万维网的浏览器或接口的网络环境中实施。尽管未要求,但是本发明可经由开发人员或测试人员所使用的应用程序编程接口(applicationprogramminginterface;API)来实施,和/或包括在网络浏览软件内,其将在由一个或更多个计算机(例如,客户端工作站、服务器或其他装置)执行的诸如程序模块的计算机可执行指令的总体情形下加以描述。通常,程序模块包括用来执行特定任务或实施特定抽象数据类型的例程、程序、对象、组件以及数据结构等。通常,程序模块的功能性可视各种实施例的需要加以组合或分布。此外,本领域技术人员将理解,本发明通过其他计算机系统配置实施。可适合与本发明一起使用的其他公知计算系统、环境和/或配置包括,但不限于,个人计算机(PC)、服务器计算机、手持式或膝上型装置、多处理器系统、基于微处理器的系统、可编程电子消费品、网络PC、微型计算机以及主机计算机等。本发明的实施例还可在分布式计算环境中实施,在所述环境中由经由通信网络或其他数据传输介质链接的远程处理装置来执行任务。在分布式计算环境中,程序模块可位于包括存储器存储装置的本地和远程计算机存储介质两者中。因此,图1示出可实施本发明的合适计算系统环境100的示例,尽管如上文已清晰描述,但是计算系统环境100仅仅是适合计算环境的一个示例,且并非旨在对本发明的使用或功能性的范围提出任何限制。同时,也不应理解为计算环境100具有与示例性操作环境100中所说明的组件中的任何一个或其组合相关的任何独立性或要求。参照图1,用于实施本发明的示例性系统包括呈计算机110形式的通用计算装置。计算机110的组件可包括(但不限于)处理单元120、系统存储器130,以及将包括系统存储器的各个系统组件耦接到处理单元120的系统总线121。系统总线121可以是包括存储器总线或存储器控制器、外设总线和本地总线的若干类总线结构中的任何一个,其中上述各类总线使用多种总线架构中的任何一种。作为示例,但并非限制,此类架构包括工业标准架构(IndustryStandardArchitecture;ISA)总线,微通道架构(MicroChannelArchitecture;MCA)总线,增强型ISA(EnhancedISA;EISA)总线、视频电子标准协会(VideoElectronicsStandardsAssociation;VESA)本地总线、外设组件互连标准(PeripheralComponentInterconnect;PCI)总线(也称作夹层总线),和PCI-Express总线。计算机110通常包括多种计算机可读介质。计算机可读介质可以是计算机110可访问的任何可用介质,且包括易失性和非易失性,可移动和不可移动介质两者。作为示例,但并非限制,计算机可读介质可包括计算机存储介质和通信介质。计算机存储介质包括易失性和非易失性、移动和不可移动介质两者,其可以任何方法或技术实施以便存储信息,诸如计算机可读指令、数据结构、程序模块或其他数据。计算机存储介质包括(但不限于)随机存取存储器(RAM)、只读存储器(ROM)、电可擦可编程只读存储器(EEPROM)、闪存或其他存储器技术、只读光盘(CDROM)、多功能数码光盘(DVD)或其他光盘存储、磁盒、磁带、磁盘存储或其他磁存储装置,或可用来存储所要信息且计算机110可访问的任何其他介质。通信介质通常含有计算机可读指令、数据结构、程序模块或模块化数据信号中的其他数据,诸如,载波或其他传送机制,且包括任何信息传递介质。术语“模块化数据信号”是指具有以特定方式设定或更改后就可将信息编码到信号中去的一个或更多个特性的信号。作为示例,但并非限制,通信介质包括有线介质,诸如有线网络或直接有线连接,以及无线介质,诸如声波、射频(RF)、红外线和其他无线介质。上述各类介质的任何组合也可包括在计算机可读介质的范围内。系统存储器130包括呈易失性和/或非易失性存储器形式的计算机存储介质,诸如,ROM131和RAM132。含有基本例程的基本输入/输出系统133(BIOS)通常存储于ROM131中,所述基本例程有助于在计算机110内的元件之间转移信息,诸如有助于在启动期间传输信息。RAM132通常含有可直接访问处理单元120和/或当即在处理单元120上运作的数据和/或程序模块。作为示例,但并非限制,图1示出操作系统134、应用程序135、其他程序模块136以及程序数据137。RAM132可含有其他数据和/或程序模块。计算机110还可包括其他可移动/不可移动、易失性/非易失性计算机存储介质。仅作为示例,图1示出从不可移动的非易失性磁性介质读取或写入至其的硬盘驱动器141,从可移动的非易失性磁性磁盘152读取或写入至其的磁盘驱动器151,以及从可移动的非易失性光盘156读取或写入至其的光盘驱动器155,诸如,CDROM或其他光学介质。可用于本示例性操作环境的其他可移动/不可移动、易失性/非易失性计算机存储介质包括(但不限于)盒式磁带、闪存卡、多功能数码光盘、DV录像带、固态RAM以及固态ROM等。硬盘驱动器141通常经由不可移动存储器接口(诸如,接口140)连接到系统总线121,且磁盘驱动器151和光盘驱动器155通常经由可移动存储器接口(诸如,接口150)连接到系统总线121。上文论述的以及图1示出的装置及其相关联的计算机存储介质存储用于计算机110的计算机可读指令、数据结构、程序模块以及其他数据。举例来说,在图1中,硬盘驱动器141示为存储操作系统144、应用程序145、其他程序模块146以及程序数据147。请注意,这些组件可与操作系统134、应用程序135、其他程序模块136以及程序数据137相同或者不同。本文中操作系统144、应用程序145、其他程序模块146以及程序数据147以不同符号表示,以便说明它们至少有所不同。用户可经由输入装置(诸如,键盘162和定位装置160,通常称作鼠标、轨迹球或触控板)键入命令和信息到计算机110中。其他输入装置(未图示)可包括麦克风、摇杆、游戏手柄、卫星天线、扫描仪等。这些和其他输入装置通常经由耦接到系统总线121的用户输入接口160连接到处理单元120,但可经由其他接口和总线结构连接,诸如,并口、游戏口或通用串行总线(USB)。监视器191或其他类型的显示装置也经由诸如视频接口190的接口连接到系统总线121。除监视器191以外,计算机也可包括诸如扬声器和打印机(未图示)的其他外设输出装置,其可经由输出外设接口195来连接。计算机110可在使用逻辑连接来连接到一个或更多个远程计算机(诸如,远程计算机180)的网络环境中运作。远程计算机180可以是个人计算机、服务器、路由器、网络PC、对等装置或其他通用网络节点,且尽管图1仅示出存储器存储装置181,但是远程计算机180通常包括上文针对计算机110所描述的大部分或全部元件。图1描绘的逻辑连接包括局域网(LAN)171和广域网(WAN)173,但也可包括其他网络。这类网络环境在办公室、企业级计算机网络、企业内部网和因特网中很常见。当计算机110在LAN网络环境中使用时,计算机110经由网络接口或适配器170连接到LAN171。当计算机110在WAN网络环境中使用时,计算机110通常包括用于经由WAN173(诸如,因特网)建立通信的构件。在网络环境中,针对计算机110所描绘的程序模块或其部分可存储在远程存储器存储装置中。作为示例,但并非限制,图1将远程应用程序185示为驻留在存储器装置181中。远程应用程序185包括(但不限于)诸如微软因特网信息服务(InternetInformationServices)和ApacheHTTP服务器(ApacheHTTPServer)的web服务器应用程序,上述应用程序提供在远程存储装置181'或可访问万维网的其他存储装置上驻留的内容。应理解,所示网络连接是示例性的,且可使用在计算机之间建立通信链接的其他构件。本领域技术人员可理解,计算机110或其他客户端装置可部署为计算机网络的部分。在这一方面,优选实施例涉及任何计算机系统,其具有任何数目个存储器或存储单元,以及跨越任何数目个存储单元或卷进行的任何数目个应用程序和过程。本发明的一个实施例可适用于具有远程或本地存储的环境,其中服务器计算机和客户端计算机部署在网络环境中。优选实施例也可适用于具有编程语言功能性、解译和执行能力的独立计算装置。示例性网络环境图2示出可实施本发明的实施例的网络环境的实施例。网络环境200含有许多本地服务器系统210,其可包括许多文件服务器211、web服务器212,以及由本地网络的所有者拥有并管理的应用程序服务器213。这些服务器与本地用户系统220通信,其可包括大量系统,诸如工作站221、桌面计算机222、膝上型计算机223,以及瘦客户端或终端机224。诸如在工作站221、桌面计算机222和膝上型计算机223的情况下,本地用户系统220可含有其自身的持久性存储装置。它们也可访问本地服务器210所提供的持久性存储,诸如,数据库。在瘦客户端或终端机224的情况下,网络存储可以仅仅是可用的持久性存储。本地网络内的用户通常经由本地服务器系统210和一些典型的网络安全性措施(诸如,防火墙270)来访问诸如因特网280的较广范围的网络。还可存在可与本地服务器系统210和本地用户系统220通信的许多远程系统290。远程计算机系统可以是多种远程终端机291、远程膝上型计算机292、远程桌面计算机293以及远程web服务器294。图2示出示例性网络环境。本领域技术人员应理解,本发明的教导可与任何数目个网络环境和网络配置一起使用。客户端-服务器环境客户端-服务器软件架构模型是多用途的、基于消息的并且模块化的基础设施,其旨在改进相对于集中式主机分时计算的可用性、灵活性、互操作性和可扩充性。客户端-服务器描述两个计算机程序之间的关系,其中一个程序(客户端,定义为服务请求方)向另一程序(服务器,定义为服务提供方)提出服务请求,而另一程序满足该请求。客户端-服务器应用程序是包括客户端和服务器软件两者的分布式系统。客户端软件程序可发起通信会话,而服务器等待来自任何客户端的请求。在网络中,客户端-服务器模型提供便捷的方式来高效地互连分布在不同位置的程序。使用客户端-服务器模型的计算机之间的事务非常普遍。大多数因特网应用程序,诸如电子邮件、web访问和数据库访问,是基于客户端-服务器模型。举例来说,web浏览器是用户计算机上的客户端程序,其可用以访问全世界任何web服务器上的信息。对于想要在远程计算机上检查银行帐户的顾客来说,可在web浏览器内运行的客户端程序向银行的web服务器程序转发请求。web服务器程序又可向数据库客户端程序转发请求,所述数据库客户端程序向另一银行计算机上的数据库服务器发送请求,以便获取所请求的帐户金额信息。金额信息被返回到银行数据库客户端,随后又返回到顾客计算机上的web浏览器客户端,其将这些信息显示给顾客。图3示出多层客户端服务器架构的示例。多层客户端-服务器架构向不同层分配不同任务和服务。图3的示例性多层架构存在3个逻辑层。第一层310是一个或更多个客户端311、312,第二层是应用程序服务器321,且第三层330是数据服务器331、332。在客户端层上,客户端311、312提供应用程序的用户接口,并用作呈现服务器。应用程序的图形用户接口通常是将由web浏览器显示在客户端计算机上的定制生成式网页。一个或更多个应用程序服务器321可作为业务逻辑的主机,且一个或更多个数据服务器331、332提供数据存储和验证服务。应用程序的主体在共享主机312上运行。应用程序服务器321并不驱动图形用户接口,而是与业务逻辑、计算和数据获取引擎共享。所获取到的数据的呈现由客户端层上的呈现服务器来处理。客户端系统上的软件越少,与安全性相关的问题就越少。与软件分布在许多桌面客户端上相比,软件集中在单个服务器上时应用程序的可扩充性、支持成本和安装成本都变得更有利。可通过在应用程序服务器层中使用组件技术来实现许多不同的实施方案,诸如,通用对象请求中介架构(CommonObjectRequestBrokerArchitecture;CORBA)、Java企业Bean(EnterpriseJavaBeans;EJB)以及分布式组件对象模型(DistributedComponentObjectModel;ECOM)。在一个优选实施例中,系统在其架构中实施EnterpriseJavaBeans(EJB)技术。EJB是Java应用程序编程接口(API),其使得开发人员能够关于于模型的实际业务架构上,而不用担心连接所有工作部分所需的无穷无尽的编程和编码。开发人员可设计(或购买)所需的EJB组件,并视需要将它们布置在服务器上。EJB是一种用于开发和部署基于组件的分布式应用程序的组件架构。使用EJB编写的应用程序可扩充、可处理事务,并且在多用户的情况下也能保证安全性。这些应用程序可以在一次性编写完成之后部署在支持EJB规范的任何服务器平台上。在EJB多层环境中,客户端提供用户接口逻辑,业务规则被分隔到中间层,并且数据库是信息仓库。客户端并不直接访问数据库。相反,客户端呼叫中间层上的EJBServer(EJB服务器),其随后访问数据库。EJBServer提供用于部署基于组件的分布式应用程序的中间层逻辑的框架。EJBServer的高性能事务服务器对客户端会话、线程、数据库连接和事务流提供高效管理。web浏览器经由HTTP连接到EJBServer或web服务器,以便下载含有Java小程序(applet)的HTML网页,而所述Java小程序用来执行呈现功能性。小程序与EJBServer通信,调用执行业务逻辑的中间层组件。数据服务器和存储服务器存储、处理并保护公司数据。EJBServer管理连接到数据库的连接池,协调连接到那些服务器的事务处理。优选实施例这个形式的优选实施例教导用于软件应用程序的自动化开发的方法和系统。方法包括以下各种过程:用于定义应用程序的过程,用于对将由软件应用程序执行的特定业务过程或功能建模的过程;用于为了进一步定义过程或功能而创建唯一特殊化UML模型的过程,以及用于针对预定义的唯一语法规则集合对模型进行验证的过程。经验证的模型随后唯一地变换成唯一的元数据形式,其包括目标应用程序使用的所生成的应用程序代码和XML文件。图4提供根据优选实施例方法的软件工程过程主要步骤的大体示意图。一般来说,使用优选实施例的软件工程过程包括以下步骤:首先使用UML图形设计工具410来设计并建模业务过程。使用本发明提供的增强版UML和元数据来建模业务过程。对UML模型和元数据进行验证420,并且将UML模型和元数据作为自动化代码生成引擎430的输入。自动化代码生成引擎解析UML模型和元数据,并使用企业应用程序开发框架(又称作Palmyra框架)来生成针对目标应用程序480的可部署源代码。有时候需要一些手动编码450来补充自动生成的代码,但与传统方法相比,手动编码量大幅减少,并且通常针对特定或特殊化的应用程序特征。优选实施例还可包括配置工具460以及测试和检测工具470。一旦配置及测试完成,目标应用程序准备好进行部署490。I.使用UML图的软件模型的图形设计这个形式的优选实施例提供易于使用的图形软件工程工具。自动代码生成过程起始于使用UML设计工具(诸如,MagicDraw或RationalRose)的标准建模方式。使用上述这些工具来创建UML图,以便呈现所要的业务过程和所要的数据模型。用户和顾问都可使用图形建模和设计工具。优选实施例促进包括业务组件和技术组件两者的现有组件的重复使用。在本发明的一个实施例中,图形建模和设计工具基于商用UML可视化建模工具,诸如,MagicDraw。仅仅MagicDraw并不足以用作优选实施例的图形建模和设计工具。尽管MagicDraw用作可视化画图工具,但它无法检查设计错误、无法控制范型(Stereotype)和标记值(TaggedValue)、无法拒绝错误数据,也无法提供警告。当将MagicDraw用作工具来构建并设计UML模型时,本发明创建Designer工具作为MagicDraw的插件来增强功能。增强型UMLDesigner,也称作PalmyraUMLDesigner,组成位于MagicDraw之上的附加层,以便解决无法创建不遵循预定义规则的UML模型的限制性,并在设计过程期间及之后避免错误。PalmyraUMLDesigner采用以下步骤来实现上述优势。第一步,PalmyraUMLDesigner工具通过验证初始值、多样性和类型等,来检查所设计的模型是否遵循预定义Palmyra规则。第二步,PalmyraUMLDesigner工具确保各图准备好用于生成过程而并无人为错误。第三步,PalmyraUMLDesigner工具使得能够在整个应用程序中精确地添加和更改关系和简单(Simple)字段。第四,PalmyraUMLDesigner工具检查Palmyra元素,并添加或校正其Stereotype之间的新资格(eligibility),以便避免冲突和设计错误。最后,PalmyraUMLDesigner工具利用TaggedValue而不是StringValue(字符串值)的值引用。优选实施例并不限于MagicDraw或任何其他特定的UML设计工具。因此,技术人员可通过使用其他设计工具,诸如,独立应用程序,或追加另一UML可视化设计工具,来实施上述验证功能性。UMLDesigner还提供有助于用户创建UML模型的可用性特征。UMLDesigner提供panel(板)、class(类)和TaggedValue输入的用户友好接口。UMLDesigner自动装载项目内遵循优选实施例的模型。UMLDesigner通过将Palmyra类分成4个主要分类简化了Palmyra类的使用,所述4个主要分类分别是Entity(实体)、Interface(接口)、Controller(控制器)和SimpleValue(简单值)。UMLDesigner依据选定类型向类添加所需要的Stereotype。UMLDesigner在运行时还显示可用父类型(parenttype)。PalmyraUMLDesigner还可向选定设计工具提供新动作集合。图5示出UMLDesigner的File(文件)菜单500,其具有示例性新动作。NewPalmyraProject510:这个子菜单用来新建Palmyra项目。Palmyra项目含有PalmyraUML模型,且去除所有冲突Stereotype。PalmyraSave520:保存活跃项目。ValidatePalmyraProject530:这个子菜单用来验证项目的Palmyra规则。OpenPalmyraCodeGeneration540:这个子菜单用来打开CodeGenerationTool(代码生成工具)并将其传递到相关UML模型(呈PalmyraXML格式)的完整路径下。这个子菜单在验证项目时使用。CodeGenerationTool的路径在插件安装时指定。GenerateLogFiles560:这个子菜单用来生成日志文件(logfile)。第一日志文件含有实体列表,且并不含有当前模型的代码。第一日志文件的文件名称是模型名称加上“_EntitiesWithoutCode.log”的串联。第二日志文件含有字段列表,但并不具有TaggedValue“currpath”,且并不具有simple(简单)值(字段必须具有至少一个“.”)。第二日志文件的文件名称是当前模型名称和“_FieldsWithCurrPath.log”的串联。这个子菜单在验证项目时生效。可使用UML设计工具来创建若干类型的图,诸如,类图、过程图和案例转换图(use-casetransitiondiagram)。PalmyraUMLDesigner向MagicDraw的Diagram菜单600提供附加菜单选项(图6)。A.ClassDiagram(类图)使用类图建模技术来唯一地创建类图,在所述技术中特定的预定义类型的类和装饰适用于提供唯一功能性,允许系统解释图并在生成时生成数据结构。在本发明的框架所提供的标准UML模型中,唯一地创建特定的预定义类型的类。这些类被编组成若干类型的类,诸如,Entity(实体)、Controller(控制器)、SimpleType(简单类型)和Interface(接口)。模型中的类是框架库的一部分。借助于PalmyraClassDiagrams子菜单610,在创建UML类图时PalmyraUMLDesigner提供对图形工具的直接访问。在框架所提供的相同标准UML模型中,唯一地创建特定的预定义类型的装饰。这些装饰也被编组成诸如被设计成便于创建目标软件应用程序的TaggedValue和Stereotype的类型。1.ClassTypes(类的类型)Palmyra由以下4种类的类型组成:Simple(简单)、Entity(实体)、Controller(控制器)和Interface(接口)。a.SimpleTypes(简单类型)Simple类的类型是原语结构,其含有数字、或日期或符号列表这类单个数据元素。Simple类型可由框架所提供的标准模型来预定义,且也可在目标应用程序的特定模型中定义。Simple类型用作Entity类-类型这类更复杂类的字段,或用作Controller类-类型中所含方法的参数。这些Simple类的类型也可受到约束,以便对数据元素提供限制和定义,诸如,数值型元素的取整以及文本元素和预置值的格式。预定义Simple类型的一个示例是StringValue(字符串值)。StringValueSimple类型是最大字符个数受到约束的文本结构。预定义Simple类型的另一个示例是BooleanValue(布尔值),其中数据元素的值为true(真)或false(假)。所定义的Simple类型的一个示例是AgeValue(年龄值)。在这个示例中,使用名称AgeValue来创建Simple类型,所述名称AgeValue经定义以继承另一预定义或新定义的Simple类型的属性。举例来说,AgeValue设定为继承IntegerValue(整数值),其是含有介于-2,147,483,648到2,147,483,647之间的整数的预定义Simple类型。另外,可对新定义的AgeValueSimple类型添加约束,以使得范围可在0到150之间。因此,新定义的AgeValue继承有关提供一定范围内的值的能力属性,且可用依据目标应用程序的需要所建立的特定值进一步定义AgeValue。Simple类的类型也具有Enumeration(枚举)类。枚举类描述枚举类型。在类属性中定义这种类型的可能值。图7A示出枚举(enum)类的一个示例(MyEnumeration(我的枚举))。在此特定示例中,类含有带有属性的用户列表。在此示例中,user1具有特性列表,诸如,UserName(用户名称)[i]=Developer(开发人员),UserName[i+1]=Designer(设计人员),UserName[i+3]=consultant(咨询人员)。在所生成的应用程序中,枚举类可在组合框(ComboBox)中呈现。i.TypeName(类型名称)类TypeName类是含有特定类的全部子类名称的枚举,其在运行时进行填入。图7B示出TypeName类的示例。举例来说,如果类型名称的扩展部分是“ConstraintTypeName(约束类型名称)”,且TaggedValue“classname(类名称)”的类值是“X”,那么运行时系统的组合框中将显示类“X”中Stereotype为“constraints(约束)”的所有子类的名称。ii.DynamicTypeName(动态类型名称)DynamicTypeName类是含有带有2个附加特性的给定类的全部子类的枚举,其在运行时进行填入。图7C示出DynamicTypeName类的示例。举例来说,如果用户如下定义DynamicTypeName类:将TaggedValue“classname(类名称)”的类值定义为“X”,将“includetype(包括类型)”定义为“Type_AbstractValue(抽象值)”,并将“excludetypes(排除类型)”定义为“Type_Constraintable(可约束)”,那么系统将显示“X”中扩展部分为“AbstractValue”但并不具有Stereotype为“constrainable”的所有子类。PalmyraStereotypes&Rules(Palmyra范型和规则)(下文)中详细描述了所有可能类型的描述。iii.Attribute(属性)类Attribute类用来定制从PalmyraSimple类型中的一种扩展并添加用户需要的特定特性的simple类。图7D示出Attribute类(attr)的示例(ATTR1)。Attribute类定义特定对象的特性集合。在图7D所示的示例中,为特定属性attr1定义了4个特性(max(最大值)=100,precision(精度)=3,rounding(取整)=ROUNDUP(向上取整),min(最小值)=0)。在另一个示例中,用户可定义类型“AmountValue(数量值)”的新属性,并将这个属性的TaggedValue给定为“precision(精度)”和“defaultformat(缺省格式)”,然后在应用程序中定义所有属性、参数以及运算返回值。iv.ControllerName(控制器名称)控制器名称类似于类型名称,不同之处在于baseclassname(基类名称)是控制器。图7E示出Controller类的示例(CONTROLLERNAME1)。举例来说,如果控制器名称的TaggedValue“baseclassname”的值为控制器“C”,那么运行时系统将在组合框中显示控制器“C”的所有子类的名称。v.ActionEnumeration(动作枚举)ActionEnumeration类是动态枚举,其在运行时由控制器中的方法的执行结果来填入。图7F示出ActionEnumeration类的示例(ACTIONENUMERATION1)。举例来说,为了填入文件(企业应用程序档案(EnterpriseApplicationArchive;EAR)中的特性文件)中的市场TransactionType(事务类型),用户创建控制器,定义返回CollectionValue(集合值)的方法,并随后创建ActionEnumeration类,其TaggedValue“controllername(控制器名称)”等于新控制器的名称(在图7F中=CalendarEntryController(日历条目控制器)),且其“actionname(动作名称)”等于运行时填入MarketOperationType(市场运算类型)的值的方法的名称(在图7F中=createdaily(媒体创建))。在添加、修改或删除充MarketOperationType的一些值的情况下,这些更改仅在文件中进行。b.EntityTypes(实体类型)Entity类的类型是含有字段的异类结构,所述字段具有一个或更多个Simple类的类型,且Entity类的类型可与其他Entity类的类型有关。类似于Simple类型,Entity类型可由框架所提供的标准模型来预定义,或者可在目标应用程序的特定模型中定义。Entity类型是构成目标应用程序的数据结构的数据元素,所述数据结构也可用作Controller类-类型中所含方法的参数。这些Entity类的类型也可受到约束、增强及修改,以便依据目标应用程序所建立的需要提供更精确的数据元素。Entity类的类型可针对字段和关系具有定义多样性。运行时依据预定义多样性来检查Entity类的实例(也称作对象)的完整性,以检查这些对象的正确性。Entity类的类型之间的关系分成4组,分别称作generalization(泛化)、aggregation(聚合)、composition(组合)以及association(关联)。Generalization关系用来表达继承性。继承性类视为现有类的扩展,其中可向现有类添加字段或关系,和/或可修改一些特征,诸如,现有字段和关系的多样性。Aggregation关系用来实现由一个Entity类定义的数据结构指向由另一Entity类定义的其他数据结构。Composition关系用来说明由一个Entity类定义的数据结构包含由另一Entity类定义的其他数据结构。Association关系用来依据与相关类的内容相关的条件,关联由一个Entity类定义的数据结构与由另一Entity类定义的其他数据结构。关系依赖性分成6组,它们被称为In(所属)、Contains(包含)、SameAs(相同)、Or(或)、Xor(异或)以及Exclusive(互斥)。关系依赖性适用于一对关系,且两个关系称作来源关系和目标关系。有资格具有这类依赖性的关系是Aggregation或Composition关系类型。In关系依赖性用来说明属于来源关系的元素同时是目标关系集合的成员。Contains关系依赖性用来说明属于来源关系的元素集合包括属于目标关系的元素集合。SameAs关系依赖性用来说明属于来源关系的元素与属于目标关系的元素相同。Or关系依赖性用来说明两个关系中至少一个,来源关系或目标关系,应在运行时被分配。Xor关系依赖性用来说明两个关系中仅有一个,来源关系或目标关系,应在运行时被分配。Exclusive关系依赖性用来说明两个关系中至多一个,来源关系或目标关系,应在运行时被分配。存在以下不同类型的实体:i.Entity(实体)类Entity类是数据库中的持久性类(实现接口“AbstractValue”),其具有属性(继承自“CompositeValue”)以及与其他类的关系。图9A示出Entity类的示例。实体可具有诸如(constrainable(可约束)、cached(缓存))的Stereotype,诸如(expandable(可扩展)、nonexpandable(不可扩展)和BusinessTaggedValue(业务标记值))的TaggedValue以及Attribute(属性)。ii.Constrainable(可约束)类Constrainable类是数据库中开发人员可对其定义约束的持续性类。Constrainable类是Stereotype为“constrainable”的“entity(实体)”。图8示出Constrainable类810的示例。iii.Constraints(约束)类Constraints类的目的是定义Constrainable类的约束。“Constraints”类应继承自受约束类(其Stereotype也应为“Constrainable”或“constraints”)。图8示出Constraints/Constrainable类的使用。Equity(资产净值)820、Right(权利)830和Warrant(担保)840这些类是具有特定特性(固定值、多样性)的安全性(security)。约束是:Equity820:针对这个类,属性“assetNature(资产本质)”为冻结(frozen),只读,且具有固定值“Equity”。Right830:针对这个类,属性“assetNature”为冻结,只读,且具有固定值“Right”。Warrant840:针对这个类,属性“assetNature”为冻结,只读,且具有固定值“Warrant”。iv.Composite(组合)类Composite类在数据库中不具持久性,并不实现接口“AbstractValue”,但具有属性和关系。Composite类继承自“CompositeValue(组合值)”。Composite类具有Stereotype和TaggedValue。图9B提供Composite类的示例。v.Macro(宏)类Macro类用来优化类图中相同属性的重复。当(不同类的)相同属性普遍用于许多类时,Macro的定义可非常有用。实际上,Macro表达同一类中相同属性的语义分组,以使得这些属性可供其他类使用。图9C提供Macro类的示例。d.Controller(控制器)类Controller类的类型是算法定义结构,且含有一个或更多个编写的算法(又称作Method(方法))。类似于Simple类型和Entity类型,Controller类的类型可由框架所提供的标准模型来预定义,或者也可在目标应用程序的特定模型中定义。Method可具有一个或更多个输入数据元素(又称作输入参数),且可返回至多一个输出元素(又称作返回值)。输入参数和返回值都表示Simple类的类型、Entity类的类型或接口的实例。控制器可具有作为别名的较短名称,且用作计算公式的应用程序代码或表达式在提及指定Controller时使用这个别名。图9D提供Controller类的示例。e.Interface(接口)Interface是用作模板的异类结构,所述模板含有具有一个或更多个Simple类的类型的字段,且Interface可与其他Entity类的类型或接口具有关系。类似于Simple类型和Entity类型,接口可由框架所提供的标准模型来预定义,或者也可在目标应用程序的特定模型中定义。Interface分组含有图10所示的以下接口:i.Value(值)接口“Value”1010:这个接口是框架中所有元素的超接口。所有实施类缺省不具持久性。用户可定义其自己的接口“Value”,其扩展Value或其子接口中的一个。这些新接口用来定义属性,且与其他接口或类形成关系。所有实施类不具持久性(举例来说,Stereotype为“Composite”)。ii.AbstractValue(抽象值)接口“AbstractValue”1020:这个接口是数据库中所有持久性实体的超接口。这个接口定义技术字段(pk、creationDate(创建日期)、creatorUserId(创建者用户Id)、updateDate(更新日期)、updatorUserId(更新者用户Id)、accessPoint(接入点)、type(类型))。AbstractValue的所有子接口的Stereotype必须为“abstractvalue”,且所有子类的Stereotype必须为“entity”。如果用户定义接口“abstractvalue”,那么其可定义属性(并非运算),且与其他类或接口形成关系。iii.Storage(存储)接口“Storage(存储)”:这个接口是Stereotype为“storage”的接口,其指定实施实体的存储。接口Storage必须继承自接口AbstractValue。用户必须添加相关的TaggedValue“datasource(数据源)”。实施所创建接口的所有类将存储在指定数据源中。TaggedValue的值“datasource”与实际数据库之间的映射将在部署应用程序时执行。示例:客户购买了Palmyra业务应用程序,其具有与另一应用程序的接口,但这个应用程序具有其自身的数据库。设计人员需要创建新的存储实体,其继承自接口Storage且分配到对应数据源。iv.Historicized(历史)接口“Historicized”1030:其说明实施实体将被记录成历史。系统定义两个接口:Historicized和HistoricizedOnDelete(历史删除)。Historicized实体是继承自上述两个接口中的一个的类。系统将维护对这个实体的实例进行的所有修改的历史。用户可定义其自己的接口“historicized”,其将TaggedValue定义为“historydatasource(历史数据源)”。实施所创建接口的所有类将记录在指定历史数据源中。TaggedValue的值“historydatasource”与实际数据库之间的映射将在部署应用程序时执行。图10给出这些接口的层次结构。3.ClassDecoration(类装饰)的类型特定的预定义装饰被唯一地创建TaggedValue和Stereotype,其经设计以促进目标软件应用程序的创建。类图的装饰提供接口、类、关系和字段这类元素的附加信息。装饰分成TaggedValue和Stereotype。TaggedValue用来借助于所要值(诸如,数字或字符)向元素添加信息。Stereotype经添加以对这些元素进行分类,诸如,Entity和Constraint,或者经添加以添加StereotypeConstrainable这类信息,然而并不分配值给Stereotype。可用TaggedValue和Stereotype的列表视元素的类型而有所不同。由框架所提供的标准UML模型将排他地定义所有Stereotype。另外,标准UML模型将定义一些TaggedValue,而目标应用程序的特定模型可定义其他TaggedValue。表2列出Palmyra的Stereotype和TaggedValue。表2:Palmyra的Stereotype和TaggedValuea.TaggedValue(标记值)简介Palmyra元素可具有称作TaggedValue的特性。TaggedValue是提供给接口、类、关系和字段这类元素的特性。TaggedValue可以是强制的或是可选的。所有特定TaggedValue(目标应用程序的特定模型中加以定义)是可选的。一旦将TaggedValue添加到元素,值将被分配给所述TaggedValue。TaggedValue的一个示例是CalculationFormula(计算公式)。当将CalculationFormula添加到字段时,表达式将作为值被分配给所述CalculationFormula。b.Stereotype(范型)简介Stereotype也是提供给元素的特性。不同于TaggedValue,在Stereotype使用时并未被分配值。目标Stereotype仅表示需要一个值。举例来说,当将Stereotype“Constrainable”添加或分配到Entity类的类型时,Stereotype“Constrainable”将通知系统稍后运行时可向Entity类的类型添加限制。可依据应用性的等级对Palmyra的Stereotype和TaggedValue进行分类。Stereotype和TaggedValue可定义为属性等级、类等级、关系等级或依赖性关系等级。表2列出了Palmyra的Stereotype和TaggedValue。c.类的Stereotype“entity(实体)”:Stereotype为Entity的类具持久性。“composite(组合)”:Stereotype为Composite的类不具持久性。“macro(宏)”:Stereotype为Macro的类具有一组可在一个以上类中重复的属性。这些属性将成为具有附加属性的每一类的部分属性,所述附加属性的Type为这个Macro类。Type为Macro的每一属性将在生成步骤中被这个Micro类的所有属性替换。“controller(控制器)”:Stereotype为Controller的类可仅具有运算(动作)。“typename(类型名称)”:Stereotype为Typename的类用来列出一个类的所有子类。这信息设在TaggedValue类名中。举例来说,如果用户添加TaggedValue“classname”为“StringValue”的typename类,那么type为这个typename类的每个字段将具有“StringValue”的所有子类的值。“dynamictypename(动态类型名称)”:Stereotype为Dynamictypename的类是Typename类的变型。除了classname以外,用户可指定included(包括)和excluded(排除)类型。用户可指定以下9种类型:type_AbstractValue(抽象值)、type_Interface(接口)、type_CompositeValue(组合值)、type_Constraintable(可约束)、type_Constraints(约束)、type_CollectionValue(集合值)、type_SimpleValue(简单值)、type_BusinessEntity(业务实体)、type_ExcludeAll(排除全部)以及type_IncludeAll(包括全部)。“attr(属性)”:Stereotype为Attr的类可针对Palmyra的Simple类型的元数据有附加限制。用户可指定具有所有所要特性的定制Simple类型,所述特性诸如缺省format(格式)、mask(屏蔽)、max(最大值)、min(最小值)、precision(精度)以及rounding(取整)。“enum(枚举)”:Stereotype为Enum的类表示枚举。其属性呈现type为“enum”的字段的所有可能值。每一Enum类的元素应继承自Palmyra的StringValue类型或其子类中的一个。“controllername(控制器名称)”:Stereotype为Controllername的类可列出控制器的所有子类。这信息设在TaggedValue“baseclassname”中。“actionenum(动作枚举)”:Stereotype为Actionenum的类具有运行时被动态分配的值。Actionenum具有两个TaggedValue:controllername和actionname。Actionenum类的可能值是与TaggedValue“controllername”中所指定的控制器相关的TaggedValue“actionname”中所指定的动作的执行结果。d.接口的Stereotype“value(值)”:“value”接口是非持久性接口。“abstractvalue(抽象值)”:stereotype为“abstractvalue”的接口是持久性接口。其所有子类可保存到任何存储服务。“Storage(存储)”:stereotype为“storage”的接口用来识别“datasource(数据源)”(数据库),其可供所有实施实体使用。“historicized(历史)”:stereotype为“historicized”的接口用来识别“historydatasource(历史数据库)”(数据库),其用来存储所有实施实体的历史表。e.与View(视图)相关的元素这些元素有助于定义实体属性和关系的缺省视图。这些特性将添加到供Palmyra的Presentation(呈现)服务所使用的元素的元数据。“invisible(不可见)”:TaggedValue为“Invisible”的属性可用来使得所有服务路径下的相关联对象无法查看。如果用户想要特定路径下的对象变为可见,那么用户必须使用视图格式来添加。“style(样式)”:TaggedValue为“Style”的属性可用来使用特定样式来检查对象。样式的值可以是Palmyra所支持的布局中的一种。所述值也可含有用于确定条件的标准,其必须经过验证以便应用特定布局。“order(序列)”:TaggedValue为“Order”的属性含有给出视图序列内的位置的整数值,其中特定对象的序列将在被检查类内被检查到。用户必须仔细,以避免针对两个不同对象使用相同序列。“label(标签)”:TaggedValue为“Label”的属性将使用标签中的指定值来查看。“readonly(只读)”:TaggedValue为“Readonly”的属性无法修改。“frozen(冻结)”(使用UML编辑器中的可换性特性来定义):当设为属性时,UML设计器必须向属性提供一个初始值,且其缺省视图是只读(ReadOnly)模式。f.与Database(数据库)相关的元素“mandatory(强制)”:(使用UML编辑器中的可换性特性来定义,见表1):当在属性等级设置时,这个属性说明这个字段的值必须设为一个值而不能为空值。“index(索引)”:TaggedValue设为“Index”的属性必须在数据库中进行索引,以便加速查找性能。当在类等级定义时,这个属性用作TaggedValue,且设成必须进行索引的属性组(例如,index=key1,key2,key3)。如果必须对一个以上组进行索引,那么必须设定若干TaggedValue。“unique(唯一)”:Stereotype设为“unique”的属性说明这个元素在数据库中具有唯一约束。当在类等级定义时,这个属性用作TaggedValue且设成必须唯一的属性组(例如,unique=key1,key2,key3)。如果一个以上组必须唯一,那么必须设定若干TaggedValue。“unique”也验证“mandatory”特性和TaggedValue“index”。“datasource(数据源)”:与Stereotype一起使用,这个接口TaggedValue指定实现这个接口的所有实体(及其子类)所使用的数据库。UML中指定的值将在PalmyraSetup(设置)工具运行时映射到实际数据库。“historydatasource(历史数据源)”:这是用在接口中的TaggedValue,其扩展接口“Historicized”。“historydatasource”用来指定用于历史记录的数据源。“code(代码)”:code是唯一地表示对象的字符串。code包括其属性或关系集合中的一个或一串。缺省的实体代码是其数据库主键(primarykey)。当属性或关系具有Stereotype“code”时,这说明这个属性或关系是对象代码的部分。如果代码被组合,那么Stereotype属性必须使用TaggedValue“orderincode(次序代码)”来排序,“code”也验证“mandatory”特性以及Stereotype“index”和“unique”。“asp”:这是个用于属性的Stereotype,以便管理不同用户之间的全局实体的共享。用户仅允许访问相关联实体的子集。管理员必须设置用户特性,以便透明地将其映射到asp属性,从而确定允许访问哪个子集。“indexgroup(索引组)”:这个TaggedValue用来说明带有这个属性的相关联组必须在数据库中进行索引,以便加速查找性能。“uniquegroup(唯一组)”:这个TaggedValue用来说明带有这个属性的组在数据库中具有唯一约束。“skewed(斜行)”:当这个TaggedValue设为true时,对象必须传递到SQL查询作为其值的内容而不是作为预备语句。“transient(暂态)”:说明这个属性或关系是暂态的,且不会映射到数据库中。g.与Constraint(约束)模型相关的元素“constrainable(可约束)”:这个Stereotype说明类是受到约束的。这个Stereotype在从超类创建受限类时是强制的。“constraints(约束)”:这个Stereotype说明类的超类具有约束。受约束类可在运行时更改其部分超特性,诸如,Attribute(属性)范围和关系基数。“originalname(原始名称)”:这个TaggedValue与受约束类的关系相关联,以便说明覆写关系(或角色)的原始名称。Stereotype类是其超类的约束。h.与Model(模型)相关的元素“sequence(序列)”:这个Stereotype与将被动态分配到唯一序列值的属性相关联。“set(集合)”:set是应用到1到n组合和聚合关系的缺省Stereotype。“list(列表)”:list是应用到1到n组合和聚合关系的Stereotype。list依据用户定义的序列对其拥有的元素进行索引。这些元素将依序显示,且可使用上下箭头或“orderlist(排序列表)”动作重新排序。“map(映射)”:map是应用到1到n组合和聚合关系的Stereotype。map依据用户定义的角色(键)对其拥有的元素进行索引。“indexname(索引名称)”:这个TaggedValue说明施加给属性的索引的名称。“indexisunique(索引唯一)”:这个TaggedValue用来定义唯一性条件,所述唯一性条件对“map”关系中index字段和所有者的对称角色两者进行分组。施加这类唯一条件时,针对索引字段的每一可能值仅返回一个集合项。未施加nounique(不唯一)约束时,一个以上项可与索引字段的每一可能值相匹配。在这种情况下,关系将为隐藏的,且无法经由Palmyra的缺省呈现接口来创建或更新集合。i.与Dependency(依赖性)关系相关的元素对于所有依赖性关系,以下3个TaggedValue是强制的:“root(根)”:说明依赖关系所属的基类。“source(源)”:说明来源关系的角色。“target(目标)”:说明目标关系的角色。Stereotype定义所需依赖性关系的类型。“sameas”:说明依赖关系的目标类是相同的。“in”:说明来源关系必须是目标类的集合中的一个。“contains”:说明目标关系的集合包括在来源关系的集合中。“exclusive”:说明可设定来源关系和目标关系中至多一个。“or”:说明可设定来源关系和目标关系中至少一个。“xor”:说明仅可设定来源关系和目标关系中的一个。j.SLATaggedValue“slaname”:这个TaggedValue含有继承自Palmyra接口的SLAInterface(SLA接口)的类的名称。“context(上下文)”:这个TaggedValue含有用来查找SLA的参数。k.SOAStereotype“interface”:这个Stereotype仅可应用于Stereotype为“controller”的类。对于属于“interface”控制器的方法,所有参数和返回值无法是Interface或CompositeValue(组合值)、CollectionValue(集合值)、ListValue(列表值)和MapValue(映射值)。这个约束无法应用于方法的任何子类。Interface说明这个控制器的方法可为Palmyra以外的应用所用。“reference(参考)”:这个Stereotype仅可应用于Stereotype为“controller”的类。Reference说明这个控制器方法的所有实施可存在于Palmyra以外的应用中。l.其他TaggedValue“orderincode(次序代码)”:这个TaggedValue是整数值,其给出构成代码的属性组内特定代码的排序。这个Stereotype与Stereotype“code”相关。“alias(别名)”:这个TaggedValue用于控制器,以便指定其唯一别名。这有助于通过别名而并非全名来调用控制器。控制器可具有一个以上别名。“controllername”:这个TaggedValue与Stereotype“actiondynamicenum(动作动态枚举)”一起使用。“controllername”说明控制器的类名称,其含有返回值列表(enum)的方法。“actionname”:这个TaggedValue与Stereotype“actiondynamicenum”相关。“actionname”说明返回值列表的方法。“possiblevaluesformula(可能值式)”:这个TaggedValue仅可应用于聚合关系。“possiblevaluesformula”的值必须是有效标准,且将在获取关系的可能值时加以使用。“rounding”:这个TaggedValue可应用于type为“DoubleValue(双精度值)”的属性。“rounding”用来指定将应用到属性值的取整类型。“wordsize(字尺寸)”:这个TaggedValue指示给出呈现侧所显示的最大字长的数值。“wordsize”在很长字符串的搜索结果中非常有用。“defaultformula(缺省式)”:这个TaggedValue含有将经过计算作为缺省值的表达式。“calculationformula”:Calculationformula(计算公式)用来说明字段或关系会依据计算表达式而自动分配。公式可依据Entity类中定义的其他字段或关系。表达式是应用到字段或关系值、或应用到Controller类的类型中所定义的调用方法的结果上的算术或逻辑运算子列表。如果字段或关系具有计算公式,那么这意味着字段或关系的值在运行时无法进行手动分配。“calendarpath(日历路径)”:这个TaggedValue含有业务日历的完整路径。“curpath(货币路径)”:这个TaggedValue含有货币类的完整路径。“domainmanager(域管理员)”:这个TaggedValue含有实施接口DomainManager(域管理员)的java类的完整路径。“active(活跃)”:当字段处于关注状态,那么这个TaggedValue“active”就被设定为true。每当这个字段未被关注时,“active”将被重新刷新。“ownerclassname(所有者类名称)”:当字段的type为KeyNameValue(键名称值)、CriterionValue(标准值)或ExpressionValue(标定值)时,必须指定这个TaggedValue。“ownerclassname”含有键的所有者类的引用。“ownerclasspath(所有者类路径)”:当字段的type为KeyNameValue、CriterionValue或ExpressionValue时,必须指定这个TaggedValue。“ownerclassname”含有键的所有者类的完整路径。“BusinessTaggedValue(业务标记值)”:这是由BusinessTeam(业务团队)定义的特殊Stereotype。这个Stereotype下定义的全部TaggedValue将在所有UML元素(诸如,类、字段、关系结束(RelationEnd)、接口)的TaggedValue的子类别BusinessTaggedValue中显示。“storename(存储名称)”:这是用户可指定逻辑存储名称的TaggedValue。“storename”用来存储type为“FileName(文件名称)”或其一个子类的属性的值。用户可使用Setup(设置)工具使特定存储与每一storename相关联。存储可以是文件夹或远程存储装置,诸如ftp。“fieldconfig(字段配置)”:这个TaggedValue用来指定与实现HasIncompleteState(具有完成状态)接口的类相关的配置。用户可选择与选定实体相关的字段列表。“descriptionkeys(描述键)”:这个TaggedValue允许用户指定描述实体的键列表。,这个TaggedValue中指定的键列表将用来在呈现侧呈现实体。“ortarget(或目标)”:用户可使用这个TaggedValue在当前字段与同一实体中或有关系的另一实体中的另一字段之间定义“or”依赖性。“xortarget(异或目标)”:用户可使用这个TaggedValue在当前字段与同一实体中或有关系的另一实体中的另一字段之间定义“xor”依赖性。“exclusivetarget(互斥目标)”:用户可使用这个TaggedValue在当前字段与同一实体中或有关系的另一实体中的另一字段之间定义“exclusive”依赖性。m.Palmyra类型i.Palmyra的Simple类型Palmyra的Simple类型能够依据业务需要进行个性化调整。用户可定义其自己的类型(继承自Simple类型),并添加其所要调整的合适值的属性(Stereotype为“attr”)。表3列出Palmyra的Simple类型。表3:Palmyra的Simple类型ii.Palmyra的特殊化类型Palmyra提供特殊化类型,以便允许特定功能的实施。这些类型包括实体类型和接口。表4列出Palmyra的特殊类型。表4:Palmyra的特殊类型Status表示生命周期状态的属性的类型AbstractValue用来定义持久性对象的类型,其等效于Stereotype“entity”CompositeValue用来定义非持久性对象的类型Value用来定义非持久性对象的接口Historicized允许记录实体实施的历史的接口C.过程图使用状态图建模技术来唯一地创建过程图,在所述技术中特定的预定义的装饰适用于提供唯一功能性,以使得系统能够解译各图并在稍后运行时运行过程。特定的预定义装饰经唯一地创建Tagged-Value和Stereotype,其经设计以促进创建目标软件应用程序。过程图表示过程定义(ProcessDefinition)。过程定义列出开始点与结束点之间发生的状况。过程图包括系统和用户所执行的所有活动。过程包括许多个步骤。借助于使用状态图建模技术,由状态来表达步骤,且用转换来表达互连性。使用两个预定义的状态来定义过程的开始和结束。状态之间的转换可由事件来触发,且由条件来保护。一个事件可触发以特定序列定义的多个转换。当满足第一条件时,过程由具有所述满足条件的转换转到下一步骤。状态分成持久状态和非持久状态两类。持久步骤是过程可停止等待外部事件的检查点,且非持久步骤表示由系统进行的活动。1.过程装饰列表过程图的装饰提供状态和转换这类元素的附加信息。装饰也同样分成TaggedValue和Stereotype。a.TaggedValueTaggedValue是提供给接口、类、关系和字段这类元素的特性。TaggedValue可以是强制的或是可选的。所有特定TaggedValue(目标应用程序的特定模型中加以定义)是可选的。一旦将TaggedValue添加到元素,值将被分配给所述TaggedValue。TaggedValue的一个示例是CalculationFormula。当将CalculationFormula添加到字段时,表达式将作为值被分配给所述CalculationFormula。类似于类装饰中的TaggedValue,过程装饰中的TaggedValue是提供状态和转换这类元素的特性。TaggedValue可以是强制的或是可选的。目标应用程序的特定模型中无法定义特定的TaggedValue。一旦将TaggedValue添加到元素,值将被分配给所述TaggedValue。TaggedValue的一个示例是应用到转换的Order(次序)。1、2和3等这类数字将分配给这个TaggedValue,以便表示次序。b.StereotypeStereotype也是提供给元素的特性。不同于TaggedValue,在Stereotype使用时并未被分配值。目标Stereotype仅表示需要一个值。举例来说,当将Stereotype“Constrainable”添加或分配到Entity类的类型时,Stereotype“Constrainable”将通知系统稍后运行时可向Entity类的类型添加限制。同样类似于类装饰中的Stereotype,过程装饰中的Stereotype是提供状态和转换这类元素的特性。在Stereotype使用时并未被分配值。目标Stereotype仅表示需要一个值。举例来说,当将Stereotype“Persistent(永久性)”添加或分配到状态时,Stereotype“Persistent”将通知系统在所述步骤停止过程且等待事件。2.案例转换图使用状态图建模技术来唯一地创建案例转换图,在所述技术中特定的预定义的装饰适用于提供唯一功能性,以使得系统能够解译各图并在稍后运行时创建案例动作。特定的预定义装饰经唯一地创建Tagged-Value和Stereotype,其经设计以促进创建目标软件应用程序。案例转换图表示系统与用户之间经由用户接口的交互情境。交互情境由状态图中各状态所表示的一组案例组成,且其间的互连性由转换来表达。运行时,案例由用户屏幕来表示,且转换由屏幕上显示的按钮这类动作来表示。借助于单击这些按钮,系统显示所述按钮所表示的转换确定的另一屏幕。案例转换图的装饰提供状态和转换这类元素的附加信息。案例转换图的装饰仅限于TaggedValue。TaggedValue的一个示例是Action名称,其添加到转换时将向稍后在屏幕上显示的按钮提供一个标签。3.案例图PalmyraUMLDesigner工具使用状态图建模技术来创建UML案例图。这个工具可在设计时定义案例、案例之间的导航,且定义案例所允许的动作。生成工具将使用这个设计来生成相对于所定义的所有案例和动作的寄存代码。设计人员可借助于案例的简图来定义所有动作和针对每一案例所允许的不同动作。新子菜单“PalmyraUCsDiagrams”620添加到UMLDesigner的Diagram菜单600中(图6)。这个图允许设计人员绘制其自己的案例并定义所述案例所允许的不同动作。用户可通过简单的单击项“PalmyraUCsDiagrams”中的菜单来创建这个图(图6)。在创建新图后,用户可手动为其添加Stereotype“usecase(案例)”。然后设计人员可添加他的特定案例和动作。a.案例:生成工具向案例提供一个缺省名称,例如,“USECASE1”。在这种情况下,这个名称可修改为“UCAgency”1110(图11)。用户可查询并修改其特性。以下是各字段的说明:UseCase:含有案例的名称。ClassName:含有案例将被寄存到的类。可为空,在这种情况下案例可寄存到任何类。SuperUseCase:含有超案例名称。可为缺省Palmyra(例如,edit(编辑)、searchInput(搜索输入)、view(查看)等)或用户定义的案例。ButtonInputConfiguration:允许用户定义准备案例所用的信息。用户也可使用PalmyraUMLDesigner接口上提供的专家按钮填入一些专家信息。UseCaseResult:是这个案例可返回的参数集合。b.动作处理器为了创建动作处理器,设计人员必须单击工具栏上的相关按钮。然后设计人员必须通过拖放来指定来源案例和目标案例。图11展示动作处理器“AgencyCommandSearch(代理命令搜索)”1130,其寄存在案例“UCAgency”1110中。用户可查询并修改案例的特性。以下是各字段的说明:Name:含有动作处理器的名称。ActionName:其含有动作的缺省标识符,其视动作类型而定。ViewOrder:含有动作的次序。Position:含有动作在屏幕上的位置,可能值为顶部、底部,或顶部和底部。NavigationType:说明来源案例与目标案例之间的导航的类型。ToBeOverridden:说明程序员是否被允许逾越动作处理器的一些方法。ButtonShowExpert:显示动作处理器的高级信息。如果用户是动作特性信息方面的专家,那么他可单击按钮“ShowExpert(显示专家)”来定制一些特性。上下文的各字段如下:ActionType:表示动作的类型。Technical:这类动作是不可见的。Submission:这类动作显示在视图中。RowOperation:这类动作针对集合中每一行显示。ColumnOperation:这类动作针对集合中每一列显示。TableOperation:这类动作在集合的头部显示,导航动作(next,last)属于这类。ActionName:动作类型为submission时这个字段含有动作的标识符。这个字段含有角色名称。ClassName:这个字段含有这个动作将被寄存的类的名称。UseCase:这个字段含有来源案例的名称。InCollection:这个字段说明动作是否将由集合来执行。独立屏幕显示与目标案例相关的目标信息:NavigationType:动作执行后,这个特性说明应用是停留还是转至下一页。OnReturnAction:返回目标案例时将执行的动作的名称。OnReturnActionType:返回目标案例时将执行的动作的类型。ActionType:表示动作的类型。Technical:这类动作是不可见的。Submission:这类动作显示在视图中。RowOperation:这类动作针对集合中每一行显示。ColumnOperation:这类动作针对集合中每一列显示。TableOperation:这类动作在集合的头部显示,导航动作(next,last)属于这类。ActionName:这个字段含有动作的标识符。ClassName:这个字段含有目标案例的类的名称。UseCase:这个字段含有目标案例的名称。InCollection:这个字段说明目标案例是否用于集合。用户可通过修改参数(诸如,Key:视图的标识符)来修改动作的外观。LabelKey:标签资源文件内的标签的键。LabelProvider:提供方获得标签资源文件的完整路径。ImageSrc:图象的名称。ConfirmationMessageKey:确认消息资源文件内确认消息的键。ConfirmationMessageProvider:提供方获得确认消息资源文件的完整路径。AccessKey:键盘快捷键。AccessKeyProvider:提供方获得访问键资源文件的完整路径。CollapseCurrentScreen:指定动作执行后屏幕是否折叠。c.Wizard(向导)案例:优选实施例提供通过使用WIZARD方法生成案例图的另一方法来。借助于UMLDesigner,设计人员可通过案例的简图来定义向导和针对每一案例所允许的不同动作。图12A示出Palmyra的示例性类图,其演示向导如何起作用。当新图添加到UMLDesigner的PalmyraWizardDiagrams菜单630中(图6)时,这个图允许设计人员绘制其自己的向导和向导的不同步骤。用户可通过简单的单击项“TalmyraWizardDiagrams”630中的菜单来创建这个图(图6)。在创建新图之后,UMLDesigner工具自动添加Stereotype“usecase”和“wizard”。用户向新图提供一个名称,且这个名称将是运行时菜单“Wizard”下菜单项的名称。接下来,设计人员可添加他的特定步骤(图12B)。在图12B的示例中,向导具有3个步骤。第一步是用户创建客户端,“CreateClientStep(创建客户端步骤)”1240;第二步是用户创建安全性帐户“CreateSecurityAccountStep(创建安全性账户步骤)”1250;以及第三步是用户创建现金帐户1260。在通过单击工具栏中的相关按钮来创建案例之后,用户可通过拖放来在其优选位置输入案例。工具向案例提供一个缺省名称,例如,“USECASE1.”。这个名称可进行修改,例如,案例可被称作“CreateClientStep”1240。用户可查询并修改案例的特性。以下是各字段的说明:UseCase:含有案例的名称。ClassName:含有案例将被寄存到的类。这个字段可为空。InputParameters:填入这个案例的字段的参数集合。用户可在相关网格中添加一个以上参数。这个网格含有以下两列:(1)KeyName:在SLA的情况下,值或上下文的键名。(2)Formula:含有经评估具有相关KeyName的公式。OutputParameters:表示当前步骤的结果的参数集合。用户可在相关网格中添加一个以上参数。输出参数的评估可在输入参数之前完成。这个网格含有以下两列:(1)KeyName:所有向导步骤的全局映射的键。(2)Formula:含有经评估具有相关KeyName的公式。设计之后,用户必须用按钮“ValidatePalmyraProject(验证Palmyra项目)”来验证项目,随后用按钮“SaveGeneratedUML(保存生成的UML)”保存UML。最后,在PalmyraGeneration工具中,用户装载所生成的UML,并生成与他的模型相关的java类。d.向导动作处理器为了创建向导动作处理器,设计人员必须单击工具栏上的相关按钮。然后设计人员必须通过拖放来指定来源和目标向导案例。图12B展示动作处理器“CreateSecurityAccount(创建安全性账户)”1250。用户可通过双击查询并修改动作处理器的特性。以下是各字段的说明:Name:这个字段含有动作处理器的名称。ActionName:这个字段可具有以下4个不同的值:(1)Next:当ActionName是Next时,这个动作执行动作保存,且评估参数,且最终设定为next值;(2)viewSLA:当ActionName为viewSLA时,这个动作依据参数建构上下文,并进行SLA搜索;(3)createNewSLA:当ActionName为createNewSLA时,这个动作借助参数的评估结果来创建新SLA;(4)finish:当ActionName为finish时,这个动作终止向导。Position:这个字段含有动作在屏幕上的位置。ToBeOverridden:存储在这个字段的值说明程序员是否允许逾越动作处理器的一些方法。InputParameters:用户可在相关网格中添加一个以上参数。这个网格含有以下两列:(1)KeyName:在SLA的情况下,值或上下文的键名。(2)Formula:含有经评估具有相关KeyName的公式。OutputParameters:用户可在相关网格中添加一个以上参数。输出参数的评估可在输入参数之前完成。这个网格含有以下两列:(1)KeyName:所有向导步骤的全局映射的键。(2)Formula:含有经评估具有相关KeyName的公式。设计之后,用户必须用按钮“ValidatePalmyraProject”来验证项目,随后用按钮“SaveGeneratedUML”保存UML。最后,在PalmyraGeneration工具中,用户装载所生成的UML,并生成与他的模型相关的java类。III.验证验证由自动创建或验证来完成,或者正如您所做的,验证很像word处理文档中的拼写检测。另外,可实施手动的工程级别验证。视需要提供警告和错误通知以便于指导和校正。设计阶段之后,用户可以单个步骤的形式或通过系统提供的接口(诸如,“ValidatePalmyraProject”)验证整个项目或其部分。验证之后,以单个步骤的形式或通过系统提供的接口(诸如,“SaveGeneratedUML”)保存所生成的UML。通过单个步骤或系统所提供的接口(诸如,PalmyraGenerationtool),用户可装载所生成的UML,并生成与模型相关的java类。IV.代码生成A.Palmyra代码生成工具Palmyra代码生成工具是从UML模型生成企业应用程序档案(Ear)文件的应用程序。所生成的Ear文件准备好部署于应用程序服务器中。代码生成将在所生成的Ear文件中缺省包括部署应用程序所需要的所有Palmyrajar文件。新Ear也包括与Palmyra的XML文件夹相关的所有缺省配置。Palmyra生成工具可生成与应用程序的UML模型相关的java类和与控制器相关的接口。系统也可在用户图形接口的Logs(日志)部分显示GenerationSteps(生成步骤)列表。1.选择Palmyra应用程序屏幕代码生成的第一步是创建新的企业应用程序档案(Ear)文件或选择现有Ear文件。a.创建新应用程序这个选项允许在用户指定的文件夹下创建新Ear。这个新应用程序含有缺省服务和配置(图13A)。代码生成将在新Ear文件中缺省包括部署应用程序所需要的所有Palmyrajar文件。新Ear也包括与Palmyra的文件夹XML相关的所有缺省配置。生成还有其他2种设置。Generatethegeneratedcodeonly(仅生成所生成的代码):如果选择这个选项,那么代码生成将仅生成与应用程序的UML模型相关的java类和与控制器相关的接口。ShowLog(显示日志):如果选择这个选项,那么系统将在用户图形接口的Logs(日志)部分显示GenerationSteps(生成步骤)列表。当用户选择新Ear文件的生成路径,然后按下按钮Next(下一步),他将进入Ear的版本。当他按下OK(确定),指定路径下将生成新Ear文件。图13A示出如何使用Palmyra生成工具创建新应用程序。b.打开现有应用程序当用户选择打开现有应用程序这个选项,他必须首先选择系统文件夹下的旧Ear。然后用户选择按钮Next,来转到Generation(生成)或屏幕更新的屏幕。SaveConfigurationFile(保存配置文件):如果用户需要保存所有配置步骤,那么他必须为含有相关特性的配置文件指定路径。earPath:Ear文件的完整路径。sharedPack:保持由逗号隔开的共享包列表的字符串。例如,com.pahnyra.arch.broker,com.palmyra.arch.devices.input,com.palmyra.arch.devices.output,com.pahnyra.arch.miapping,...。generateJavaDoc:可设为true或false。isCreation:说明文件是创建的新Ear还是现有Ear文件的更新。prefix:前缀的名称(若存在前缀),否则设为空字符串。classPath:用来编译所生成的java类的Palmyrajar列表。listJarWar:所添加的jar和war的列表。generationPack:待生成的选定包。umlFilePath:待生成的XML文件的完整路径。generatedCodeOnly:如果为true,那么将在并不更新Ear文件的情况下生成并编译java类。verify:如果为true,那么将在并不生成任何java类的情况下验证XML文件。businessServicesPath:将自动添加到Ear文件的业务服务目录的路径。sequenceStore:如果为true,那么用户可在Setup侧指定他自己的序列数据存储。2.生成屏幕用户一旦创建新Ear文件或选择现有Ear文件,用户可在生成屏幕上设置生成选项。两个子屏幕组成生成屏幕,一个称作UMLSource(UML源),而另一个称作GenerationOptions(生成选项)。a.UMLSource(UML源)在UMLSource屏幕(图13A)中,用户可选择待生成的UML文件(强制),选择业务服务路径(可选),排除或包括待生成的应用程序的一些包,且添加或去除共享包。将缺省生成所有包,而不存在共享包。b.GenerationOptions(生成选项)在这个屏幕(图13B)中,用户可添加或去除将用来编译所生成的java类的一些jar文件,且可选中以下相关选项:GenerateJavaDoc(生成Java文档):这个选项允许生成所生成的java类的JavaDocumentation(Java文档)。ConfigurableSequencestore(可配置序列存储):这个选项允许用户在Setup侧配置序列数据存储。OnlyVerification(仅验证):如果选中这个选项,那么代码生成器将仅检查UML模型的有效性。在这种情况下,代码生成将不会影响Ear文件的修改。当未选中这个选项时,代码生成将影响Ear的新修改。图13B示出使用Palmyra生成工具的生成选项。3.更新屏幕更新屏幕向用户提供更新现有Ear文件的功能性。两个子屏幕组成更新屏幕,一个称作Services(服务),而另一个称作Configurations(配置)。a.Services(服务)屏幕屏幕Services用来添加、编辑或去除服务,按钮“BuildServices(构建服务)”将应用选定Ear文件中的修改(参照图13C)。b.Configurations(配置)屏幕屏幕Configurations用来添加、去除或恢复配置文件。屏幕Configurations也允许构建配置。用户可添加或去除视图格式的配置、应用程序服务器配置、标签配置、生命周期配置、报告配置和事务配置(参照图13D)。按钮“Remove(去除)”将从Ear去除选定文件,且按钮“Restore(恢复)”用来取消用户进行的修改。当用户单击按钮“BuildConfiguration(构建配置)”,用户进行的所有修改将生效。图13D示出使用Palmyra生成工具的配置选项。4.输出文件生成过程一旦成功,将生成以下若干文件:Ear文件、名称分别为GeneratedCodeSrc.jar和GeneratedCode.jar的生成源和lib(库)jar、含有未解压文件GeneratedCode.jar的文件夹类、含有解压文件GeneratedCodeSrc.jar的文件夹src以及含有UML中宣称将由程序员实施的控制器的文件夹MucSrc。B.Palmyra代码生成1.Palmyra自动代码生成AutomaticGeneration(自动生成)是在并不使用CodeGeneration工具的情况下生成Ear、从XML文件生成java类、借助jar和war列表更新Ear以及借助配置文件列表更新Ear的一种方式。图14示出自动生成过程的主要步骤,其包括以下步骤:1)将UML模型转化成XML文件1410;2)使用XML文件来生成Java源代码(称作所生成的源代码)1420;以及3)使用JSDK编译器来编译所生成的Java源代码,且创建库Java档案或JAR1430。将UML模型转化成XML文件可通过使用PalmyraUMLDesigner来达成。元素:代码:Simple类型和实体的Java类UML接口的Java接口对应于(稍后手动扩展以提供方法的实施)控制器的抽象控制器类用来管理屏幕等级动作(可视需要通过添加手动编写的代码来加强)的动作处理器类XML文件:Constraintmodeldescriptionfile(约束模型说明文件):含有系统稍后运行时将装载的约束的说明Processdescriptionfiles(过程说明文件):每一过程的过程说明文件含有稍后运行时将装载的过程的说明有2种方法来使用自动生成:简单调用静态方法或使用特性文件。a.使用自动生成-借助调用静态方法借助于使用代码生成工具或处理自动生成,开发人员能够生成Ear、从XML文件生成java类、借助jar和war列表更新Ear以及用配置文件列表更新Ear。这个文档描述每一选项所执行的步骤。使用自动生成来执行生成。如果使用代码生成工具,那么重现同一情境。使用自动生成的第一种方法是调用类AutomaticGeneration中的静态方法generate()。这个方法有19个参数。表5中列出相关参数。表5:Palmyra自动生成参数-File(文件)earFile:将创建或更新的Ear文件。-String(字符串)codeGenerationPath:含有Palmyra的所有jar的代码生成路径。其必须含有以下4个目录:“exf”、“extLib”、“xml”和“lib”。这些目录在生成新Ear时使用。-boolean(布尔值)isCreation:如果为true,那么将创建新Ear。新Ear将含有文件夹“exf”和“extLib”中的所有jar。同样,将文件夹“xml”中的所有xml文件设为Configs_config.jar和PalmyraRessources.jar。-StringumlFilePath:UMLDesigner插件所生成的xml文件的路径。这个文件将用来生成java文件和“GeneratedCode.jar”。-booleansequenceStore:如果为true,那么序列数据存储将为可配置的。因此用户可在Setup侧说明序列表的数据源。-booleanverifyOnly:如果为true,那么将不创建所生成的代码,且将仅验证UML模型。-StringgenerationPackages:这个字符串保持将生成的(由逗号隔开的)包列表。如果这个字符串为空值,那么将生成UML模型中的所有包。-StringsharedPackages:这个字符串保持共享(由逗号隔开的)包列表。这个字符串将设为“GeneratedCode.jar”中的文件“sharedPackages.properties”。-Stringprefix:这个字符串表示共享包的前缀名称。-Stringversion:Ear文件的版本。-booleangeneratedCodeOnly:如果为true,那么将仅生成java类。-StringclassPath:在编译所生成的java类时需要classPath。如果为空值,那么将自动计算类路径:其含有代码生成目录中的所有现有jar。-booleangeneratedJavaDoc:如果为true,那么将创建所生成的java类的javadoc(文档)。将创建新jar“GeneratedCodeLib.jar”。-StringbusinessServicesPath:将自动添加到Ear的业务服务jar的路径。将仅添加对应于UML中使用到的模型的jar。如果指定路径下缺失一些jar,那么可在Ear路径下找到的文件名称为“GenerationWarnings.log”日志文件中将会编写警告。-Collection(集合)updatedServices:含有Ear中添加或更新的jar和war列表的文件集合。-CollectionupdatedConfigurationFiles:含有添加到Ear的配置文件列表的文件集合。每个文件将添加到“Configs_config.jar”或“PalmyraRessources.jar”(从其名称切换获得)。-StringlogFilePath:日志文件的路径。如果为空值,那么将取文件“AutomaticGeneration.log”的值。-StringcompilerPath:将使用的编译器的路径(当用户想要使用特定java编译器时,例如,带有java1.5编译器的编译)。-StringcompilerVersion:将使用的编译器的版本(当用户想要使用特定java编译器时,例如,带有java1.5编译器的编译)。所有这些参数的组合允许开发人员执行一个或更多个选项:i.从头开始创建Ear文件如果参数“isCreation”为true,且Ear文件并不为空值,那么将创建空白Ear。表6所示的参数列表表示这个选项的一个示例:表6从头开始创建Ear文件的示例性StringearFilePath="D:/Test/Test.ear";StringcodeGenerationPath="D:/PALMYEA11.2/codeGeneration";booleanisCreation=true;StringumlFilePath=null;booleansequenceStore=false;booleanverifyOnly=false;StringgenerationPack="";StringsharedPack="";Stringprefix="";Stringversion="1.0";booleangeneratedCodeOnly=false;StringclassPath=null;booleangenerateJavaDoc=false;StringbusinessServicesPath=null;CollectionupdatedServices=null;CollectionupdatedConfigurationFiles=null;StringlogFilePath="D:/BUG.log";StringcompilerPath=null;StringcompilerVersion=null;AutomaticGeneration.generate(newFile(新文件)(earFilePath),codeGenerationPath,isCreation,umlFilePath,sequenceStore,verifyOnly,generationPack,sharedPack,prefix,version,GeneratedCodeOnly,classPath,generateJavaDoc,businessServicesPath,updatedServices,updatedConfigurationFiles,logFilePath,compilerPath,compilerVersion);-如果参数codeGenerationPath为null(空值)或空字符串,那么将其设定为项目目录的父目录。在任何情况下,codeGeneration目录通常含有以下文件夹:xml:含有服务配置所使用的xml文件ext:含有PalmyrajarextLib:含有外部库如上文所提到的,ext目录含有在框架Palmyra内安装、部署和使用所生成的应用程序锁需要的所有PalmyraJar。下图展示ext目录的内容。不同于ext目录,extLib文件夹仅包括PalmyraComponents(Palmyra组件)以外的文件。一些组件供框架用于特定目的(举例来说,用于解析XML文档或管理模板)。下图展示文件夹extLib的内容。文件夹xml含有一些框架组件所使用的xml配置文件。最常用来配置呈现标签和视图格式。文档的这个部分的目的是展示如何在并不生成GeneratedCode.jar或更新Ear的情况下创建Ear,因为所有参数umFilePath、updatedServices和updatedConfiguratioriFiles都为空值。借助调用以下方法:AutomaticGeneration.generate(newFile(earFilePath),codeGenerationPath,isCreation,umlFilePath,sequenceStore,verifyOnly,generationPack,sharedPack,prefix,version,GeneratedCodeOnly,classPath,generateJavaDoc,businessServicesPath,updatedServices,updatedConfigurationFiles,logFilePath,compilerPath,compilerVersion,hasJsf,excludedSharedPack);参数applicationName提供ear文件的名称(不含扩展名“.ear”)。在这个示例中,applicationName="Essai"执行以下步骤:步骤1:创建临时文件夹在codeGeneration文件夹下创建目录TMP。在这个示例中,TMP将放在以下路径下:“D:\Projects\PALMYRA11.0\FRAMEWORKL\build\out\codeGeneration”。在这个新目录下,我们可以复制目录ext和extLib文件夹(在codeGeneration目录下)下的所有内容。-在codeGeneration文件夹下创建目录Workingfolder。-在新目录Workingfolder下创建目录unEar。-在目录unEar下创建目录basedir。-在目录basedir下创建目录META-INF。-在目录unEar下创建目录config。步骤2:构建应用程序文件-将xml文件“application.xml”从当前目录(在包“com.palmyra.tools.builder”下)复制到新目录config(codegenenration/workingFolder/uriEar/config)。-解析所复制的xml文件,然后去除忽略行(以“<!”开头)。节点“display-name”和“context-root”的值设定为applicationName(在这个示例中是“Essai”)的值,且节点“web-uri”的值设定为earFile名称(在这个示例中是“Essai.ear”)。文件“"application.xml”是针对J2EE应用的部署说明。这个文件必须放在顶层META-INF目录下。-将XML文件“ibm-application-ext.xml”从当前目录(在包“com.palmyra.tools.builder”下)复制到目录config,且也移除忽略行。对于新复制的文件,我们关注于命名为“moduleExtensions”的任何元素的任何属性下命名为“xml:type”的每一项。如果我们找到值为“applicationext:WebModuleExtension”的项,那么我们将属性“altRoot”的值更改成“ALT-INF/”+applicationName+“.war”。将XML文件“jboss-app.xml”从当前目录(在包“com.palmyra.tools.builder”下)复制到目录config。对于新复制的文件,我们将节点“loader-repositoryfocus”的值设为“com.vermeg.services:loader=<applicationName>.ear”。然后将修改后的xml文件复制到目录workingFolder/unEar/basedir/META-INF下。这类文件的实用性在于通过配置为一域来分离每一应用程序的类装载器。-将所有修改后的应用程序文件(apphcation.xml、ibm-application-bnd.xml、ibm-application-extxml、jboss-app.xml)复制到目录workingFolder/unEar/basedir/META-INF下。我们也看复制文件“was.policy”(在包“com.palmyra.tools.builder”下)到这个目录下。-在目录Workingfolder下创建目录unWar。-在目录unWar下创建目录config。步骤3:-复制codegenenration/workingFolder/unWar/config下的xml文件“web.xml”,针对新复制,特性“display-name”的值将设为applicationName的值。(记住applicationName="Essai")。元素“web-app”下的属性id将设定为同一值。下图展示这些修改。-在unWar下创建目录basedir。-在Workingfolder下创建目录config。-在Workingfolder下创建目录handleConfig。-创建含有earFile的终极目录(在这个示例中,我们将创建目录“D:\Essai_codegen”)步骤4:处理外部文件夹-迭代目录TMP的内容。如果文件是war文件:如果是ear的war:war文件的名称是应用程序的名称,我们从war清单中获取war的版本,否则(如果仅仅是添加的war)获取这类war的清单文件的属性“earversion”的值。然后将这类war文件的内容提取到(目录unWar下的)目录basedir下。如果文件是ear文件:将这类ear的内容提取到(unEar下的)文件夹basedir下,然后我们迭代这个ear的内容,且针对遇到的文件(ear、jar或war)递归进行相同动作。如果文件是jar文件且其文件名称不同于“GeneratedCode.jar”,将其复制到文件夹unEar/basedir下。-在目录unWar下创建目录META-INF。-在这个目录下,创建清单文件“MANIFEST.MF”。在这类文件中,我们创建属性“Created-By”,其值设为“Palmyraat<currentDate>”,且创建属性“Manifest-Version”,其值设为“1.0”。然后,针对获取到的每一war版本,创建相关的新属性。-将jar文件“unEar/basedir/service.jar”的内容提取到目录unEar/basedir/service下。步骤5:更新未解压的service.jax-解析文件“workingFolder/Unear/basedir/service/META-INF/ejb-jar.xml”,以便查找节点“ejb-name”下名称类似于“AsynchronousX”的元素,这类元素将重命名为“Asynclrronous<applicationName>”(在这个示例中,为“AsynchronousEssai”)。-对于XML文件“workingFolder/Unear/jasedir/service/META-INF/weblogic-ejb-jar.xml”,然后将执行以下修改:-将“ejb-name”下名称类似于“AsynchronousX”的每一元素重命名为“Asynclrronous<applicationName>”。-将“jndi-name”下每一元素的值设为applicationName。-将“local-jndi-name”下每一元素的值设为Local<applicationName>。-将“connection-factory-jndi-name”下每一节点的值设为“ApplicationsQueueConnectionFactory”。-将“destination-jndi-name”下每一节点的值设为“<applicationName>Pending”。对XML文件“unEar/basedir/service/META-INF/jboss.xml”实施相同的修改,但将“destination-jndi-name”下每一节点的值设为“queue/<applicationName>Pending”。针对元素“ejbBindings”下的XML文件“workingFolder/unEar/basedir/service/META-IF/ibm-ejb-jar-bnd.xml”,将属性“jndiName”的最终值设为applicationName,且将属性“listenerlnputPortName”的最终值设为“applicationName>ServiceListener”。步骤6:创建jar文件service.jar我们依据目录workingFolder/unEar/basedir/service的内容创建jar“service.jar”,其清单为workingFolder/unEar/basedir/service/META-DST/Manifest-mf。然后我们删除文件夹服务。步骤7:处理配置文件将目录codeGeneration下的文件夹xml的内容复制到文件夹workingFolder/config下。对于XML文件“workingFolder/config/service.Resource.xml”,我们执行以下修改:-将属性“dataSource”的值设为“DataSource”。-将属性“JmsCormectionFactoryName”的值设为“ApplicationQueueConnectionFactory”。-将属性“LocalJndiName”的值设为“Local<applicationName>”。-将属性“nonXaDataSource”的值设为“<applicationName>NonXaDataSource”。-将属性“ServiceQueueName”的值设为“<applicationName>Pending”。下图展示这些修改:对于XML文件“workingFolder/config/appServersConfig.xml”,执行以下修改:-对于根节点“AppServerConfigurations”下的所有节点,关注属性“initialContextFactory”的值。如果值为“weblogicJndi_WLinitialContextFactory”,那么将属性“securityProvider”的值设为“weblogic”。如果值为“orgjnp_interfaces__NamingContextFactory”,那么将属性“securityProvider”的值设为“jboss”。如果值为“com_ibm_websphere_naming_WsnInitialContextFactory”,那么将属性“securityProvider”的值设为“websphere”。步骤8:创建特性文件夹迭代特性文件“/com/palmyra/arch/tool/updator/config.properties.”的内容。对于遇到的每一特性,创建新目录,其名称为特性的值;新文件夹创建在workingFolder/handleConfig下。在这个示例中,在目录“D:\Projects\PALMYRA11.0\FRAMEWORK\build\out\codeGeneration/workingFolder/handleConfig”下,将创建以下文件夹:Configs_config\LabelsConfigs_config\ViewformatConfigs_config\AppViewformatConfigs_config\ReportsConfigs_config\AppSerConfigs_config\TransactionsConfigs_config\LifeCyclePalmyraesourcesworkingFolder/config下的每个文件将被复制到从其名称切换获得的对应目录下:名称以特性名称(特性文件中:config.properties)开头的文件将被复制到名称为这个特性的值的所创建目录下。举例来说,xml文件“appServersConfig.xml”将被复制到目录“workingFolder/handleConfig/Configs_config/AppSer”下。如果文件名称不与任何特性名称匹配,那么这个文件将被复制到目录workingFolder/handleConfig/Configs_conifig下。步骤9:创建configjar文件-在workingFolder/handleConfig下,我们创建目录“META-INF”,然后在这文件夹下,我们创建清单文件“manifest.mf”,其中我们放入以下属性:Manifest-Version="1.0"Created-By=“Palmyraat<Thesystemdate>“Version="Palmyra:Config:<version>"+将版本的值作为参数提供给所生成的方法。这个文件将用作以下将创建的jar的清单:-jar文件“workingFolder\unEar\basedir\Configs_config.jar”,其将从目录“workingFolder\handleConfig\Configs_config”的内容创建获得。-jar文件“workingFolder\unEar\basedir\DeploymentConfig.jar”,其将从目录“workingFolder\config”的内容创建获得。-jar文件“workingFolder\unEar\basedir\PalmyraResources.jar”,其将从目录“workingFolder\handleConfig\PalmyraResources”的内容创建获得。步骤10:创建war文件-将jar文件“unEar/basedir/webService.jar”的内容提取到目录unEar/basedir/webservice下。-依据目录unEar/basedir的内容在这个目录下创建war文件<applicationName>.war(在这个示例中是Essai.war)。war的目录Web-Inf将含有文件夹“unEar/basedir/webservice/com/palmyra/arch/webservice/web”的所有内容,.class和.scc文件除外。步骤11:创建ear文件-我们为ear“workingFolder\unEar\basedir\META-INF\manifest.mf”创建清单文件。在这个清单中,我们填入以下特性:-Manifest-Version=“1.0"-Created-By"=“Palmyraat<Thesystemdate>“-Class_Path=<listofallthejarfilesunderworkingFolder/unEar/basedir>在目录worlkingFolder/unEar/basedir下,我们用新创建的清单文件替换掉jar“service.jar”的清单。写入ear的清单:我们创建清单文件workingFolder\unEar\basedir\META-INF/manifest.mf,且填入以下特性:-Manifest-Version=“1.0"-Created-By"=“Palmyraat<SystemDate>"-Class_Path=<listofallthejarfilesunderworkingFolder/unEar/basedir>在元素PalmyraVersionInfo(版本信息)下,将属性版本设为擦书版本的值(在这个示例中是1.0)。然后我们迭代文件夹workingFolder/unEar/basedir的jar文件,选择并非为外部jar的每一文件,因此,例如表##中列出的文件将不会被选中。对于每一选定文件,将创建PalmyraVersionInfo下的新属性。新属性的名称为选定jar文件的名称(无“.jar”),且其值为选定jar的最后修改日期。以jar文件commons-codec-1.3为例,对于这个jar,属性“commons-codec-1.33”的值将被创建为这个jar的最后修改的日期。这个新清单文件将用来更新jar“service.jar”的清单文件。-依据目录workingFolder/unEar/basedir(在这个示例中是D:\Essai_codegen/Essai.ear)的内容创建ear文件。这个ear的清单将是文件workingFolder\unEar\basedir\META-INF\manifest.mf,且其应用程序文件是xml文件workingFolder\unEar/config/application.xml。-删除文件夹workingFolder和TMP(codeGeneration目录下)。ii.仅生成所生成的代码这个选项在并不生成GeneratedCode.jar或更新ear的情况下创建Ear,因为所有参数“umFilePath”、“updatedServices”和“updatedConfiguratioriFiles”都为空值。为了生成“GeneratedCode.jar”但不更新Ear且不创建新Ear,仅将参数“isCreation’”设为false,将“umlFilePath”设为UML文件的路径,且将参数“generatedCodeOnly”设为true。此外,“updatedServices”和“updatedConfigurationFiles”必须为空值。参数“sequenceStore”、“verifyOnly”、“generationPack”、“sharedPack”、“prefix”、“version”、“classPath”、“generateJavaDoc”、“businessServicesPath”、“compilerPath”以及“compilerVersion”是生成情况下的切换集合。GeneratedCode.jar将创建在earFilePath的根目录下(如果没有编译错误)。表7所示的参数列表表示这个选项的一个示例。表7:仅生成所生成代码的示例性参数StringearFilePath="D:/Test/Test.ear";StringcodeGenerationPath="D:/PALMYRA11.2/codeGeneration";booleanisCreation=false;StringumlFilePath=“D:/Test/test.xml”;booleansequenceStore=false;booleanverifyOnly=false;StringgenerationPack=StringsharedPack="";Stringprefix="a";Stringversion="1.0";booleangeneratedCodeOnly=false;StringclassPath=null;booleangenerateJavaDoc=true;StringbusinessServicesPath=“D:/BS”;CollectionupdatedServices=null;CollectionupdatedConfigurationFiles=null;StringlogFilePath="D:/BUG.log";StringcompilerPath=null;StringcompilerVersion=null;AutomaticGeneration.generate(newFile(earFilePath),codeGenerationPath,isCreation,umlFilePath,sequenceStore,verifyOnly,generationPack,sharedPack,prefix,version,GeneratedCodeOnly,classPath,generateJavaDoc,businessServicesPath,updatedServices,updatedConfigurationFiles,logFilePath,compilerPath,compilerVersion);为了生成“GeneratedCode.jar”但不更新Ear且不创建新Ear,必须在参数“umlFilePath”中指定将生成的UML文件的路径,将参数“isCreation’”设为false,且将参数“generatedCodeOnly”设为true。同样,“updatedServices”和“updatedConfigurationFiles”必须为空值。表8列出附加的5个参数。表8:借助jar和war列表更新ear的示例性参数StringearFilePath="D:/Test/Test.ear";StringcodeGenerationPath="D:/PALMYRA11.2/codeGeneration";booleanisCreation=true;StringumlFilePath=null;booleansequenceStore=false;booleanverifyOnly=false;StringgenerationPack="";StringsharedPack="";Stringprefix="";Stringversion="1.0";booleangeneratedCodeOnly=false;StringclassPath=null;booleangenerateJavaDoc=false;StringbusinessServicesPath=null;CollectionupdatedServices=newArrayList();updatedServices.add(newFile("D:/Test/SmartPosition.jar"));updatedServices.add(newFile(”D:/Test/statemonitoring.jar"));CollectionupdatedConfigurationFiles=null;StringlogFilePath="D:/BUG.log";StringcompilerPath=null;StringcompilerVersion=null;AutomaticGeneration.generate(newFile(earFilePath),codeGenerationPath,isCreation,umlFilePath,sequenceStore,verifyOnly,generationPack,sharedPack,prefix,version,GeneratedCodeOnly,classPath,generateJavaDoc,businessServicesPath,updatedServices,updatedConfigurationFiles,logFilePath,compilerPath,compilerVersion);-如果参数codeGenerationPath为空值或空字符串,那么将其设定为项目目录的父目录。在任何情况下,codeGeneration目录通常含有以下文件夹xml、ext和extLib(参照段落“从头开始创建Ear文件”)。-如果用户未提到日志文件的路径,那么其值取为“AutomaticGeneration.log”。-如果未提到参数classPath(空值或“”),那么将自动计算类路径:其含有代码生成目录中的所有现有jar和BusinessService(业务服务)路径(如果提到)中的所有现有jar。借助调用以下方法:AutomaticGeneration.generate(newFile(earFilePath),codeGenerationPath,isCreation,umlFilePath,sequenceStore,verifyOnly,generationPack,sharedPack,prefix,version,GeneratedCodeOnly,classPath,generatejavaDoc,businessServicesPath,updatedServices,updatedConfigurationFiles,logFilePath,compilerPath,CompilerVersion,hasJsf,excludedSharedPack);执行以下步骤:步骤1:创建临时文件夹-在earpath的父路径下创建目录TEMP(在这个示例中,TEMP将创建在“D:\\Essai_codegen”下)-从xml文件(参数umlFilePath中已指定)装载对象UMLApplication-在earFilePath的父路径下删除最终文件夹(src和classes)(在这个示例中,在“D:\\Essai_codegen”下)-如果earpath的父路径(“D:\YEssai_codegen”)不存在,那么创建这个目录。-在earfile的父路径下创建新文件夹doc(在这个示例中是“D:\\Essai_codegen\\doc”)”。-修改所装载的应用程序,以便使其准备好生成代码(参照GenerationMechanism(生成机制))-在earFile目录的父目录下创建目录MucSrc-在目录“src”和“MucSrc”中创建类和控制器的源(参照GenerationMechanism)步骤2:创建特性文件-在目录src下创建特性文件“datasource.properties”。在这个文件中定义以下属性:AutotestDataSource(自动测试数据源)DataSource(数据源)SecurityStore(安全性存储)这些属性的值将在setup(设置)期间设定。-创建特性文件“gcstorename.properties”。在这个文件中将添加属性ATFiles。-在目录“src”下创建特性文件“sharedPackages.properties”。在这个文件中,我们将放入提到作为参数的前缀和共享包列表。步骤3:编译所生成的代码如果未提到编译器版本和编译器路径,那么使用缺省编译器,其路径是系统类路径变量的值。在执行编译任务之前,将编译器的错误输出重新导向到一个流,而不是导向到标准错误流,以使得编译器的错误输出可读取到错误阵列列表中。然后编译目录“src”和“MuSrc”下的所有java源。编译获得的“.class”文件将添加到“classes”目录下。步骤4:创建所生成的代码和源jar-为创建jar准备目录“classes”:在形成jar之前必须从这个目录删除文件列表。这些排除的文件是:-“MuSrc”下的所有非目录文件-所有Palmyra类-依据目录“classes”的内容形成jar文件“Test1.jar”-依据目录“src”的内容形成jar文件“Test1Src.jar”-如果提到businessServicesPath(在这个示例中,businessServicesPath="D:\ProjcctsPALMYBA11.0\TECHNICALSERVICES\out\lib”),那么迭代Umlapplication所使用的模块,针对每一模块查找名称为(theusedmodulename)Gen.jar的jar文件。举例来说,如果应用程序使用的模块是“Calendar”,那么在businessServicesPath下查找命名为“CalendarGen.jar”的文件。如果找到了文件,那么将文件复制到TMP目录下。对名称为(theusedmodulename)Impl.jar的文件重复这个步骤。-删除目录TEMP。iii.借助jar和war列表更新Ear为了更新Ear,参数“updatedServices”必须含有表示待添加的jar和war列表的“java.io.File”的集合。如果Ear文件不存在,那么丢弃这个异常。图8示出的参数列表表示这个选项的一个示例:-在ear文件的父路径下创建目录“TEMP”(在这个示例中,“TEMP”将创建在D:\\Essai_codegen下)。-复制TEMP目录下集合updatedServices的所有文件。步骤1:创建临时文件夹-在CodeGenerationPath下创建目录AppTemp-在CodeGenerationPath下创建目录workingFolder-在workingFolder下创建目录unEar-在unEar下创建目录basedir-在unEar下创建目录config-在workingFolder下创建目录unWar-在unWar下创建目录basedir-在unWar下创建目录config步骤2:构建web.xml文件这个步骤与创建新ear的情况相同(参照段落“从头开始创建Ear文件”)。步骤3:将ear文件复制到临时目录这个步骤包含将待更新的ear文件复制到CodeGenerationPath下的目录AppTemp。步骤4:处理外部文件夹将所复制的ear文件的内容提取到目录下unEar\basedir。包括在这个ear中的war文件的内容将被自然地提取到unWar\basedir下(参照段落“从头开始创建Ear文件”)。TEMP目录的内容(在这个示例中,其仅含有jar文件Agenda.jar)将被添加到目录unEar\basedir下的ear文件中。在用户借助jar文件service.jar更新ear的情况下,目录服务将被创建在unEar/basedir下,从这个目录下提取这个添加文件的内容,然后将内容重新压缩以形成jar文件service.jar。步骤5:创建war文件依据unEar/basedir的内容在这个目录下创建war文件<applicationName>.war(在这个示例中是Essai.war)。war的目录Web-Inf将含有文件夹“unEar/basedir/webservice/com/palmyra/arch/webservice/web”的所有内容,但.scc文件除外。-迭代目录AppTemp的内容(在这种情况下,这个目录仅含有经复制的ear文件)。-打开找到的ear文件的清单,并查找属性“PalmyraVersionInfo.”。如果找不到这个属性,那么丢弃这个异常。步骤6:创建ear文件-创建ear的清单并形成ear文件,如段落“从头开始创建Ear文件”中所描述。-删除文件夹workingFolder-删除文件夹AppTempiv.借助配置文件列表更新Ear文件为了向Ear添加一些配置文件,参数“updatedConfigurationFiles”必须含有表示待添加的文件列表的“java.io.File”的集合。如果Ear文件不存在,那么丢弃这个异常。每个配置文件将在“Configs_config.jar”或“PalmyraRessources.jar”(从其名称切换获得)中进行设置。b.利用特性文件使用自动生成使用自动生成的第二种方法是向特性文件填入所有需要的信息。表9所示的参数列表表示这个选项的一个示例。其将作为唯一的第一个参数传递到类AutomaticGeneration(jar“ExtemalBuilder.jar”中唯一的类)中的main方法。表9:借助特性文件使用自动生成的示例性参数StringearFilePath="D:/Test/Test.ear";StringcodeGenerationPath="D:/PALMYRA11.2/codeGeneration";booleanisCreation=true;StringumlFilePath=null;booleansequenceStore=false;booleanverifyOnly=false;StringgenerationPack="";StringsharedPack="";Stringprefix="";Stringversion="1.0";booleangeneratedCodeOnly=false;StringclassPath=null;booleangenerateJavaDoc=false;StringbusinessServicesPath=null;CollectionupdatedServices=null;CollectionupdatedConfigurationFiles=newArrayList();updatedConfigurationFiles.add(newFile("D:/Test/service.transaction_File.xmll"));updatedConfigurationFiles.add(newFile("D:/Test/VF_Presentation_ViewFormat.xml"));StringlogFilePath="D:/BUG.log";StringcompilerPath=null;StringcompilerVersion=null;AutDmaticGeneration.generate(newFile(earFilePath),codeGenre'ationPath,isCreation,umlFilePath,sequenceStore,verifyOnly,generationPack,sharedPack,prefix,version,GeneratedCodeOnly,classPath,generateJavaDoc,businessServjcesPath,updatedServices,updatedConfigurationFiles,logFilePath,compilerPath,compilerVersion);这个文件中的特性是:earPath:Ear文件的路径。isCreation:说明文件是创建的新Ear还是现有Ear文件的更新。ture或false(缺省false)。codeGenerationPath:Palmyra的目录“CodeGeneration”的路径。如果这个特性未分配到值,那么将其设为当前路径的父路径。umlFilePath:将由UMLDesigner生成的UML文件的完整路径。sharedPack:保持由逗号隔开的共享包列表的字符串。prefix:共享包的前缀。generationPack:由逗号隔开的所生成的包列表。verify:如果为true,那么将在并不生成任何java类的情况下验证XML文件。(缺省false)。generatedCodeOnly:如果为true,那么将在并不更新Ear文件的情况下生成并编译java类。(缺省false)。listJarWar:由逗号隔开的所添加的jar和war的列表。xmlConfig:将添加到Ear的由逗号隔开的配置文件列表。logFilePath:日志文件的路径。如果这个特性没有值,那么将设为“AutomaticGeneration.log”。sequenceStore:如果为true,那么用户可在Setup侧指定他自己的序列数据存储。(缺省false)。generateJavaDoc:ture或false(缺省false)。businessServicesPath:将通过比较UML文件中的导入模块与这个路径下现有jar的名称而自动添加到Ear的业务服务目录的路径。compilerPath:特定编译器(可选)的路径。compilerVersion:特定编译器(可选)的版本。classPath:用来编译所生成的代码的类路径。如果为空值,那么类路径将含有代码生成目录中的所有jar。表10表示示例性特性文件。表10:示例性特性文件*创建含有这些属性的特性文件:earPath=D:/test/Test.EarisCreation=truecodeGenerationPath="D:/Palmyra11.2/codeGeneration"umlFilePath=D/test/testGen.xmlgeneratedCodeOnly=falseprefix="d"verify=falselistJarWar=D:/test/SmartPosition.jar,D:/test/statemonitoring.jar,D:/test/test.jar,D:/test/dashBoard.warxmlConfig=D:/test/presentationContext.test.xml,D:/test/test.xmllogFilePath=D:/test/GenerationLog.logbusinessServicesPath="D:/BS"*调用类AutomaticGeneration中的main方法-使用Windows控制台>java-jarExtcanalBuildcr.jarpropertyFileName-使用批处理文件path=D:\bea\jdkl41_05\binjava-Xms256m-Xmx512m-Xdebug-Xnoagent-Djava.compiler=NONE-Xrunjdwp:trarisport=dt_socket,server=y,address=5051,suspend=n-jarExtenalBuilder.jarpropertyFileNameV.部署A.PalmyraSetupTool(设置工具)Palmyra提供类似向导的设计工具,目的在于使将所生成的应用程序部署到各个应用程序服务器(例如,BEAWeblogic、或IBMWebsphere或其他)的过程实现自动化。Palmyra设置工具隐藏了应用程序服务器的复杂本质。这个设置工具也管理与不同数据库提供商(例如,Oracle、MicrosoftSQLserver或IBMDB2)的通信。当使用设置工具进行部署步骤时,用户建立的配置可存储在文件中供未来使用。Palmyra设置工具支持多个存在系统、应用程序服务器和数据库,例如:(1)操作系统:Windows、Linux;(2)应用程序服务器:Weblogic8.1、Weblogic9.1、Weblogic9.2、WeblogiclO.O、JBoss3.2.x、JBoss4.0.x、JBoss4.2.x、Websphere5.1、Websphere6.x、WebSphere7.x;(3)数据库:Oracle(10g版本及以下版本)、DB2、DB2forz/OS、MYSQL(4.1.18版本或更高版本)、SQLserver(2000、2005及2008版本)。Palmyra设置工具提供类似向导的步骤来完成设置操作。第一步是欢迎屏幕。在欢迎屏幕中,用户可找到按钮“Options”。单击按钮“Options”将弹出含有4个选项的选项板:Security数据源具有不同特性,Sequence数据源具有不同特性,Load设置参数以及Update设置参数。第二步是指定操作系统和应用程序服务器。在这个步骤中,可选择操作系统和应用程序服务器。不同的应用程序服务器需要各种各样的详细信息。对于Weblogic9.1和Weblogic9.2来说,必须传递Weblogic的管理帐户的用户名和密码。对于Weblogic5.1来说,必须传递服务器名称和节点名称。对于Websphere6.x来说,必须传递服务器名称、节点名称和配置文件名称,且必须选择应用程序服务器的类型(网络部署或正常情况)。第三步是指定应用程序服务器的主目录和JMS供应商。对于所有版本的Weblogic应用程序服务器来说,除了JMS供应商(MQSeries或缺省JMS)以外,还必须传递应用程序服务器的主目录、将使用到的域和服务器名称。对于所有版本的JBoss来说,仅必须传递域目录。对于所有版本的Websphere来说,必须传递服务器主目录和JMS供应商。第四步是指定Ear路径。在这个步骤中指定待安装的Ear的路径。第五步是设置UserLoginParameters(用户登录参数)。在这个步骤中输入登录到所安装的应用程序的缺省帐户的用户名和密码。最后一步是设置Datasourceparameters(数据源参数)。所有应用程序需要数据源来顺利运行,这些数据源具有必须传递的参数,例如:Databasetype:数据库的类型;Operatingsystem:数据库机器上的操作系统;Hostname:数据库机器上的宿主名称;Databasename:数据库实例的名称;Username:待使用的数据库用户名称;Password:用户名的密码。用户可通过单击按钮“TestConnection”来测试与指定数据库的通信。所有PalmyraEar具有至少3个标准数据源:securitystore(安全性存储)、autotestdatasource(自动测试数据源)和datasource(数据源)。在大多数情况下,安全性存储与数据源具有相同参数,因此缺省情况下设置工具无法显示安全性存储以供输入其参数。如果想要显示安全性存储,转到选项板并选中复选框“securitystorehasdifferentproperties”(安全性存储具有不同特性)。可基于选定应用程序服务器的类型指定附加选项。对于Weblogic来说,附加选项包括:部署和配置应用程序服务器:将应用程序安装到带有所有需要的配置的应用程序服务器。去除所部署的应用程序:在安装新应用程序之前去除所有已部署的应用程序。去除JMS文件存储:从这个应用程序服务器的队列中去除所有消息。去除服务器高速缓存文件:清除应用程序服务器中的高速缓存。复制数据库驱动器:将数据库驱动器复制到这个应用程序服务器。复制ant库:将ant库复制到这个应用程序服务器。更新应用程序服务器类路径:更新应用程序服务器类路径。设置参数路径:为了使设置设置操作更快,设置参数可保存在文本文件中,其可在稍后重复使用而无需重新手动写入。用户可通过单击按钮选项板上的按钮“LoadSetupParameters”来重复使用所生成的文本文件,或者可通过单击按钮“updateSetupParameters”来更新。VI.创建数据库结构A.创建数据库表数据库结构由具有列、索引和约束的表构成。系统使用元数据来创建这个结构,所述元数据是设计阶段依据UML类图中定义的类而创建的。持久性模块依据以下规则从UML类生成表名:TableName=lastPackage+'_'+ClassName+'_'。举例来说,如果类的完整名称是a.b.c.d.MyClass,那么所生成的名称是d_MyClass_。应注意,如果所生成的名称超过30个字符,那么将从头开始截断以适应最大长度(30包括常量下划线)。举例来说,如果类名称是a.b.c.d.EntityWithLongNameForContractTest,那么所生成的名称是tyWithLongNameForContractTest_。下文表示出各个类之间的关系。图15A示出1对1关系的示例。在这个示例中,表X将含有y$code_和y$pk_。对y$code_和y$pk创建索引(仅在组合关系的情况下,对于聚合关系,UML必须如此说明)。图15B示出1对N关系的示例。在这个示例中,表Y将含有x$code_和x$pk_。对x$code_和x$pk_创建索引(仅在组合关系的情况下,对于聚合关系,系统必须如此说明)。图16示出带有接口的关系的示例。在带有接口的聚合关系的情况下,我们向与类X相关的表添加字段superlnterface$type_。这个字段含有类Y1或Y2的完整名称。注意:如果X的实例与Y1的实例有关系,那么表X_中的superlnterface$type_将设为类Y1的完整名称。在带有接口的带有多样性n的聚合关系的情况下,并不添加属性…$type_。类属性到表字段的映射依据以下规则:Fieldname=attributename+'_'例如:name-->name_在一个特定的实施方案中,如果所生成的名称超过30个字符,那么将从头开始截断以适应最大长度(30包括常量下划线)。举例来说,如果属性名称是longFieldNameForPersistenceContractTest,那么所生成的名称是nameForPersistenceContractTest_。图17示出继承性的示例。正常创建表mother_(无特殊处理)。表child_将仅含有字段pk_,其带有类Child(a2)中宣称的字段。表child_中的每次插入将伴随表mother_中的每次插入。依据完整性规则创建约束:实体E中字段F中的stereotype“unique”(唯一字段)将译为以下动作:通过向字段F添加类型约束unique来更改E_。实体E中字段F中的stereotype“code”(应为强制的)将译为以下动作:对字段F添加类型约束unique。实体E中字段F中的taggedvalue“index”将译为以下动作:对这个字段创建索引。B.更新数据库表使用迭代过程来开发目标软件应用程序。通过这个过程,每一迭代产生新版本的软件应用程序,其相比前一版本具有更多功能性。每当针对每一迭代对UML模型进行修改,应依据模型所表示的元数据更新数据库结构。通过这个过程,系统允许数据库结构自动更新而不会丢失先前输入的数据。在应用程序的开发阶段,或将已部署的应用程序升级到新版式时,应用程序的设计通常有所更新,且这些更改又会影响数据库的设计。这些更改包括向应用程序添加类/从应用程序去除类,向每个类添加字段类/从每个类去除字段。为了保留存储中的当前数据,在持久性服务中提供“UpdateTables”操作,以便修改底层存储而同时最大限度地降低数据丢失风险。本文档描述了选择“UpdateTables”操作后将执行的修改。在模型(带有n个属性)中添加新实体将译为以下动作:-在数据库中创建实体的表。-向字段pk_添加主键约束。-向表FormatData_添加n+7条记录,所述表FormatData_含有所有表的所有列的信息(n个属性,7个字段)从模型去除实体将译为以下动作:-无动作(实体的表是现有表)将模型中现有实体的名称从E更改为E2将译为以下动作:-创建新表E2_(表E_是现有表)-执行先前情境下描述的相同动作。向现有实体E添加新字段F将译为以下动作:-通过添加新字段F来更改表E_。-删除表FormatData_中与实体E相关的所有条目,然后添加新条目。去除现有实体E中的字段F将译为以下动作:-无动作(注意:如果这个字段从未被分配到)。将现有实体E中字段F的名称更改为F2将译为以下动作:-通过添加新字段F2来更改表E_。(F是现有表E_中的现有字段)-删除与表FormatData_中实体E相关的所有条目,然后添加新条目。(F无对应记录,F2有新记录)在模型(含有n个属性)中添加与另一实体具有组合或聚合关系的新实体将译为以下动作:-在数据库中创建实体的表。-向字段pk_添加主键约束-向表FormatData_添加n+9条记录(n个属性,7个字段,entity$code和entity$pk字段)。-在ConstraintsData_插入用于索引的新记录和为这个实体创建的。(下文详细描述)在两个实体之间添加组合或聚合类型的新关系将译为以下动作:-通过添加所有者的$code和$pk字段来更改在数据库中应具有外键的表。-删除表FormatData_中与应具有外键的表相关的所有条目,然后添加新条目。(包括owner$code和owner$pk)在两个实体之间添加继承性类型的新关系将译为以下动作:-无需执行动作。更改关系的多样性将译为以下动作:-如果多样性更改不是将关系从单值更改为多值,那么无需执行动作,反之亦然。-当更新关系本质时,系统更改外键在具有可导航角色的表中的位置。更改字段的类型将译为以下动作:-通过修改字段的数据类型来更改有关表,在RDBMS(关系数据库管理系统)允许的情况下继续这个步骤。-删除表FormatData_中与有关表相关的所有条目,然后添加新条目。C.更新数据库约束依据UML模型中使用字段和关系多样性来定义的完整性规则创建数据库的表约束。每当对完整性规则进行修改,必须更新表约束。系统在可能时提供数据库约束的自动更新。当由于先前的现有数据与先约束不符合而导致约束无法自动更新时,系统生成促进手动干预的报告。系统提供诸如失败约束的信息。有时候,对应用程序进行的设计更改并不包括添加/去除类或字段。有时候,您需要做的就仅仅是修改一些字段的约束。在这种情况下,无需调用“UpdateTables”操作。反之,您需要使用“UpdateTables”操作。待执行的所生成的SQL代码针对每个DBMS(数据库管理系统)各不相同。下文是选择选项“UpdateConstraints”之后将执行的修改的细节。向实体E中字段F(强制字段)添加stereotype“unique”将译为以下动作:-通过向字段F添加类型约束unique来更改E_。-更新ConstraintsData_(去除所有条目,然后重新定义新条目)去除实体E中字段F(强制)的stereotype“unique”将译为以下动作:-通过去除约束unique来更改表E_。-更新ConstraintsData_去除实体E中字段F(非强制)的stereotype“unique”将译为以下动作:-通过去除约束unique来更改表E_。-通过将F渲染为nullable(可为空值)来更改E_。-更新ConstraintsData_去除实体E中字段F的stereotype“code”将译为以下动作:-去除对F创建的约束unique。-更新ConstraintsData_向实体E中字段F添加taggedvalue“index”将译为以下动作:-对这个字段创建索引。-更新ConstraintsData_去除实体E中字段F的taggedvalue“index”将译为以下动作:-丢弃对这个字段创建的索引。-更新ConstraintsData_将实体E中字段F的多样性更改为1将译为以下动作:-通过修改F的定义(此后,F并不为空值)来更改表E_。-更新ConstraintsData_将实体E中字段F的多样性从1更改为nullable将译为以下动作:-通过修改F的定义(此后,F可为空值)来更改表E_。-更新ConstraintsData_去除组合或聚合类型的关系将译为以下动作:-丢弃对owner$code和owner$pk字段创建的索引。-更新ConstraintsData_添加聚合类型的关系将译为以下动作:-如果多样性为1,那么向添加owner$pk添加约束unique。-更新ConstraintsData_-(NOINDEXESONFOREIGNKEYS)(外键无索引)添加组合类型的关系将译为以下动作:-对外键创建索引-如果多样性为1,那么向添加owner$pk添加约束unique。-更新ConstraintsData_VI.配置A.呈现1.菜单目标应用程序菜单含有应用程序所提供的到达屏幕的所有路径。这些菜单中的每一个可含有子菜单和树状结构的附加路径。2.MenuEditorTool(菜单编辑器工具)Palmyra提供称作MenuEditorTool的工具,其用来定义应用程序菜单的结构。MenuEditorTool实现了菜单配置能力。作为脱机工具的菜单编辑器需要来自服务器的信息,所述信息包括当前菜单、系统中定义的用户、模型的类路径、动作类型、案例、自由参数以及附加参数。这个工具允许装载预建菜单配置文件,然后将这些配置文件反射到系统中。这个工具还允许装载导入/导出配置文件,所述文件允许系统导入或导出当前配置,或者通过从另一文件导入配置而获得所述配置。此外,这个工具允许操纵,其中可对当前配置文件进行操纵,且更改将应用到当前系统。另外,工具也针对不同用户组提供不同配置,并提供经配置以支持特定语言的多语标签。最后,这个工具还允许添加新菜单项。图18表示MenuEditorTool的用户接口。必须通过定义初始器并调用方法AdvancedMenuGenerator.register()来寄存配置菜单项。表11示出添加新菜单项的示例。表11:添加新菜单项的示例SimpleContextImplsimpleCtx=newSimpleContextImpl(UseCaseConstants.EDIT,Boolean.FALSE,Menu.class.getName(),ActionTypeConstants.TECHNICAL,ActionConstants.CREATE);AdvancedMenuGenerator.register(AdvancedMenuGenerator.PUBLIC,"Configuration>Menu","MenuManager"simpleCtx,null,false,MenuProvider.class.getName());在这个示例中,结构包括以下信息:Role:用于vermegadmin的AdvancedMenuGenerator.VERMEG_ADMIN或AdvancedMenuGenerator.ADMIN。path:新建项的父路径。所述路径必须以以下形式写入:item1>item2>....>parent。如果找不到这个路径,那么创建这个路径。label:项的名称。targetContext:调用的目标simple上下文。isInit:说明是否在初始化模式下查看这个项。additionalParameters:目标上下文中需要的附加参数。resource:到达资源提供方的完整路径。当完成菜单结构的创建时,系统生成含有菜单结构的文件,所述文件将装载到目标应用程序。3.View-format(视图格式)Palmyra自动生成用来创建、编辑和搜索Entity类的类型的对象的屏幕页面,所述类型在目标应用程序的UML模型中定义。使用生成缺省屏幕布局的算法,依据实体类的字段和关系来生成屏幕内容。可稍后使用View格式配置工具来手动修改表示字段和关系的可视元素(文本框、组合框、列表、链接)的使用及其在屏幕上的分布。View-format还可从屏幕去除多余字段,并可创建字段组。类com.palmyra.arch.presentation.model.viewformat.ViewFormat.的实例表示Palmyra屏幕的视图格式。这个类含有:屏幕特性:Label:含有屏幕标题(title);isForCaching:屏幕的概要(skeleton)是否可高速缓存;showTitle:屏幕的标题是否可见。字段特性:Readonly:这个字段是只读还是可编辑;Mandatory:这个字段是否是强制的,以便保存实例到数据库中;Visible:是显示还是隐藏这个字段。将一个视图格式实例链接到合适屏幕的信息存储在类文件中com.palmyra.arch.presentation.model.viewformat.FactoryEntry,存在两个字段:Context:指定对应屏幕的上下文;Precise:指定视图格式是否使用精确上下文来寄存。图23展示视图格式服务的UMLClassDiagram(类图)。3.ActionConfiguration(动作配置)Palmyra框架针对每个屏幕生成缺省动作。用户可使用ActionConfiguration服务来修改这些动作的一些特性。他可隐藏或显示动作、更改其图标、更改其位置(Top(顶部)或Bottom(底部))、更改动作安排。4.Translator(翻译器)Translator是Palmyra框架的配置模块,其管理像标签、枚举、屏幕标题等之类的许多呈现元素的国际化。a.标签自动生成的屏幕页面具有带有描述性标签的屏幕元素(文本框、组合框、列表、链接等)。使用UML类图中定义的字段名称或关系名称来生成这些标签。稍后可使用Translator模块来修改这些标签。当使用屏幕页面时,依据用户配置文件中定义的语言来选择标签。b.枚举枚举是Simple类的类型,其表示具有UML类图中定义的预定义可用值集合的文本。在屏幕页面中,具有枚举类的类型的字段显示为具有可用值集合的组合框。可使用Translator模块来修改这些可用值。当使用屏幕页面时,依据用户配置文件中定义的语言来选择可用值。5.缺省值配置缺省值配置服务允许针对特定领域和特定用户定义缺省值。这就允许了定义每一客户的不同缺省值。B.安全性1.Authentication(认证)Authentication是访问方藉以证明他/她(们)的行为代表特定用户或系统的机制。Authentication使用诸如用户/密码的凭证来回答问题,“Whoareyou?”(您是谁?)。应用程序服务供应商(ApplicationServiceProvider;ASP)的概念包括在Authentication模块中。实际上,Authentication模块将用户视为一对UserName(用户名称)和ASPValue(ASP值)。这允许了定义具有相同名称的一个以上用户(假设他们具有不同ASP值)。在Palmyra技术中,ASP是共享相同数据库的不同实体之间的数据和过程的Segregation(隔离)。实体可以是客户端所需要的银行、分支、部门或任何再分配。举例来说:ASPValue为X的用户将仅看到与X相关的数据。图19展示Palmyra的示例性登录页面。Palmyra的Authentication由两种方法完成:(I)InternalAuthentication(内部认证):认证由应用程序自身使用内建组件来管理的认证机制。此时,用户名和密码保存在数据库中。当使用内部认证机制时,应用程序提供安全性配置工具来创建新用户,这通常由系统管理员来完成。(2)ExternalAuthentication(外部认证):应用程序与用户藉以定义的外部系统通信。外部系统中存在定制寄存器,其存储用户名及其凭证(例如,LDAP,ActiveDirectory)。Palmyra中的Authentication使用Filters(过滤器)来检查用户发出的每一请求。如果是从经认证的会话发出,那么请求将被转发到所要求的资源。否则,请求将被转发到登录页面。Palmyra使用Form-Based(基于表单)的认证来向Filter发送用户名和密码,所述Filter验证用户名和密码。在ExternalAuthentication的情况下,用户名和密码存储在诸如LDAP(轻量目录访问协议)的定制寄存器中。因此第一步是确保用于部署的应用程序服务器支持带有定制寄存器的集成。应用程序服务器连接到用户寄存器,以便收集创建凭证时的用户相关信息,其然后用来在验证期间(举例来说,登录到应用程序以检查密码时)表示用户。举例来说,WebsphereApplicationServer安全性支持实施大多数主LDAP目录服务器(像Windows的ActiveDirectory)。作为另一示例,Jboss也支持实施ActiveDirectory。安全性内核提供称作AuthenticationDriver的认证接口。这个接口的实施取决于客户端所需要的认证技术。AuthenticationDriver接口含有6种方法:booleaninit():安全性认证驱动器的初始化(表达式:Loadofsetupuser)。Stringauthenticate(ServletRequestservletRequest):这个方法的实施取决于认证所用的技术。举例来说,在内部认证的情况下,我们可实施这个方法来从参数ServletRequest获得用户名、asp和密码,然后检查这对是否存在于DataStore中。在外部认证的情况下,其将被JSecurityCheckservlet(小服务程序)替换,所述JSecurityCheckservlet将起到检查用户凭证的相同作用。voidlogin(StringuserName,ServletRequestservletRequest):在缺省认证的情况下,我们实施这个方法来高速缓存sessionId(会话ID)和userName(用户名)。在外部认证(JSecurityCheck)的情况下,用户名已高速缓存在会话中。StringisAuthenticated(ServletRequestservletRequest):这个方法的实施用来在会话ID存在高速缓存器中的情况下返回用户名,否则返回空值。voidlogout(ServletRequestrequest,ServletResponseresponse):这个方法的实施允许通过无效会话使用户登出。voidfailLogin(ServletRequestrequest,ServletResponseresponse):在认证失败的情况下,方法failLogin的实施用来告知在哪里转发请求。认证驱动器的任何实施例需要以下静态块,其中我们如下寄存驱动器:static{DriversFactory.getDriversFactory().registerAuthenticationDriver(newMyAuthenticatioriDriver());}为每一个SecurityUser(安全用户)存储最后的连接日期。为了在Palmyra框架中加强安全性,通过帐户锁定和密码策略来实施帐户管理。帐户锁定和密码策略都可在称作passwordConfiguration的特性文件中配置。所含特性是:minLength:定义密码UserCredentials所需要的最小长度的整数。缺省值是0。upAndLow:定义密码UserCredentials是否同时需要大写和小写字符的布尔值。缺省值是false。mixedChars:定义密码UserCredentials是否同时需要数字和字符的布尔值。缺省值是false。passwordValidity:定义密码的以天记的有效周期的整数。这个特性缺省为空。warnBefore:定义天数的整数,在所述天数之前系统应开始警告用户需要更新其凭证。warnBefore必须与passwordVattdity一起使用。这个特性缺省为空。lockOutNbr:定义失败密码尝试次数的整数,所述次数将使用户变为无效(将SecurityUser的IsActive特性设为false)且因此无法再访问应用程序,除非管理员重新激活(将IsActive设为true)或用户在8小时后尝试。这个特性缺省为空。Palmyra还支持单点登录(SingleSignon;SSO)认证机制。单点登录能够要求用户仅登录应用程序一次,且访问许多不同应用程序组件,尽管这些组件可能有其自身的认证机制。这个特征允许终端用户针对每次会话登录一次,而不是独立登录每一资源或应用程序。2.Authorization(授权)Authorization是藉以基于用户身份或其他信息而控制用户与应用程序资源之间的交互的过程。换句话说,Authorization回答问题“Whatcanyouaccess?(您可以访问什么?)”。实施接口AumorizationDriver来定义应用程序所使用的授权过程方法。在以下不同层实施Palmyra的授权系统:a.Groups(组)为易于管理,可对系统用户进行分组。安全性配置工具允许创建分组和对应用户。组还可分组到其他组中,以便创建层次结构。第一次运行应用程序Administrators和VermegAdmin时缺省创建2个组。VermegAdmin是组Administrators的部分。如果SecurityUser属于VermegAdmin或Administrators,那么SecurityUser具有应用程序的全部特权。b.Roles(角色)角色是用来预建待应用到稍后创建的用户的配置集合的用户配置文件。使用安全性配置工具来创建这些角色。稍后使用相同的安全性配置工具来将这些角色分配给先前创建的用户。第一次运行应用程序时缺省创建角色“admin”。这个角色具有应用程序资源的全部权限。c.Rights(权限)依据用户可访问哪些Entity类的类型和用户可运行哪些过程部分来表达用户的特权和约束。使用安全性配置工具来配置权限。稍后也使用安全性配置工具来将这些权限分配给先前创建的用户、组和角色。Palmyra的授权过程在两个等级中完成。(1)Entity等级:在这个等级中系统检查用户特权。图20示出Palmyra实施的实体授权过程。(2)Service等级:在这个等级中系统检查是否允许执行特定动作。图21示出服务授权过程的过程。Palmyra中的角色由其名称(RoleId)来定义。角色附带EntityPolicies(实体策略)和ServicePolicies(服务策略)。服务策略将定义角色提供给用户或用户组的特权。为了使角色能够访问指定实体,将实体策略与Role(角色)相关联。这些关联性基于createcondition(创建条件)、updatecondition(更新条件)、deletecondition(删除条件)和findcondition(查找条件)。如果这些条件得到验证,那么被授予这个角色的用户可访问所述指定实体。通过ApplicationName:ALL或应用程序名称或EntityName来识别实体策略。“createcondition”、“updatecondition”、“deletecondition”或“findcondition”字段是可为以下值的Boolean(布尔)表达式:Empty:这意味着这个create(创建)/update(更新)/delete(删除)/find(查找)动作并无约束。"false":无权执行create/update/delete/find动作。表达式含有以下键date、hour、time、currentUser、userProperties或所述键的组合。示例:attribute==currentUser,这个delete条件意味着:依据这个角色,仅可删除属性值等于当前用户的实例。示例2:attribute==userProperties.propertyName。实体com.Palmyra.arch.basicStruct.data.BusinessEntity是业务实体的超实体。实体com.Palmyra.arch.basicStruct.data.AbstractValue是超实体(业务实体加上Palmyra实体)。为了使角色能够访问并执行特定服务中的指定动作,将服务策略与Role(角色)相关联。这些关联性基于某个条件。如果这个条件得到验证,那么被授予这个角色的用户可访问applicationname/service/action(应用程序名称/服务/动作)。通过ApplicationName(应用程序名称)、Servicename(服务名称)和Actionname(动作名称)来识别范围策略。Condition(条件)字段是可为以下值的布尔表达式:Empty:这意味着这个applicationname/service/action并无约束。"false":无权访问这个applicationname/service/action。表达式含有以下键date、hour、time、currentUser、userProperties或所述键的组合。假设给定语法identifieroperatorvalue,那么每一所述键可用作标识符或值。Date:评估为当前日期,BusinessDate的一个实例。示例:date=='10/12/2100b',例如,仅允许2100年12月10日执行动作。Hour:评估为当前小时,TimeValue的getHour()的一个实例。示例:hour==8,例如,仅允许每天8点执行动作。Time:评估为当前时间,TimeValue的一个实例。示例:time=="08:00:00:000",例如,仅允许每天8点执行动作。CurrentUser:评估为当前用户,StringValue的一个实例。示例:currentUser=="X"。UserProperties:用于安全性特性名称之前,且带有以下语法:userProperties.propertyName。后者被评估为当前用户的安全性特性值。示例:userProperties.method=="value1",例如,仅在当前用户菲菲设为值1的情况下允许执行动作。Parameters:与有以下语法:parameters.paramName一起使用,其中paramName是ServicePolicy中定义为actionName的动作的参数。示例:parameters.config.creatorUserId==currentUser,这个条件意味着需要当前用户创建参数“config”,以便允许动作执行。服务com.Palmyra.arch.service.BusiaessDelegate是超服务。图22A、22B和22C示出示例性AuthorizationUML模型的主要部分。具体来说,图22A示出示例性SecurityItem的UMLModel,图22B示出示例性Policies的UMLModel,且图22C示出示例性SecurityItem的RolesUMLModeL。当用户A访问应用程序资源时,检查用户是否被授权进行访问。这些检查的操作原则依赖于与用户A相关的实体和服务策略。当检查用户是否被授权时,从每个角色形成条件,并添加到所有角色的联合。示例:用户A需要搜索实体E的实例。用户A具有一个角色X和继承自组B的角色Y,其中角色Y是组B的成员。角色Y具有实体E的EntityPolicy实例P2,且查找条件设为creatorUserId==currentUser。这个条件意味着用户A查找E时仅可看到他创建的实例。角色X具有实体E的EntityPolicy实例P1,且查找条件设为空。考虑到后一信息,用户A将看到E的所有实例。原因仅仅是标准形成有作为联合的角色X和Y的两个条件,且作为查询发送到数据库。标准是pk!=null|creatorUserId=="A"。C.InputandOutputDevices(输入和输出装置)所生成的目标应用程序含有先前存在的库,其使用不同的通信和消息传送协议来管理与其他系统和应用程序的通信。优选实施例支持的协议示例有FTP、File、Queue、WebDav、MailviaSMTP。针对上述每一种协议,目标应用程序中都集成了输入和输出装置。为了使用InputDevice(输入装置),用户需要:用特定消息类型定义InputDeviceConfiguration(输入装置配置)。他可在菜单ConfigurationTools的子菜单IODevicesConfiguration中进行定义。定义用来实施接口InputDeviceListener的监听器类。在这个类中,他必须将他的监听器预订为特定消息类型,并实施方法onreceive(MessageHeadermh)。OutputDevice(输出装置)实施例定义2个动作器:OutputDeviceConfiguration(输出装置配置):输出装置配置是codefield为devicelD的实体类。其依据装置类型具有若干字段(举例来说,输出装置邮件配置中的邮件服务器或输出装置FTP配置中的主机姓名)。OutputDevice(输出装置):输出装置管理将值写入到装置。因此,它与输出装置配置相关联。所有输出装置应扩展抽象类OutputDevice。Palmyra定义以下5种类型的OutputDevice:OutputDeviceQueue、OutputDeviceFile、OutputDeviceFTP、OutputDevicePalmyraService和OulputDeviceMail。每一扩展的输出装置继承ByteArrayOutputStreamAttribute并实施方法flush。所继承的字段可通过调用方法getOutputStream()来获得。这个方法返回OutputStream。方法flush()将所继承字段的内容写入到由相关联的输出装置配置所定义的装置。可通过针对新I/O装置添加新模块和新库来添加新I/O和协议。通常不在运行时执行I/O装置的修改。应用程序可利用新模块和库来下线并重新部署。D.MappingTool(映射工具)Mapping是提供转化对象的能力的工具(例如,基于配置将字段值从源对象复制到目标对象)。图25示出Mapping过程的概况。1.Mapping机制的使用Mapping机制用于:a.与外部世界连接在Palmyra框架中,数据由特殊对象(接口“Value”及其实施器)表示。使用通用驱动器解析来自外部驱动器的外部数据,因此输出通常呈特定于驱动器的格式。特定于驱动器的对象应转化成上面定义有过程的应用程序数据对象。b.集成组件应用程序还使用业务服务,其可要求创建特定对象以便集成其过程。举例来说,结算业务服务的输入是结算消息(数据对象)。如果用户想要将结算集成到应用程序,那么他应创建源为其他数据对象(诸如,客户端支付)的结算消息。2.Mapping配置运行时Mapping是可配置和可定制的:整个映射配置可随时进行更改,且配置效果即刻生效。使用呈现层在应用程序运行时创建映射配置。举例来说,在路由器中,针对每一传入消息类型配置解析器(驱动器),且然后可指定映射。图26示出Mapping的配置的示例。3.Mapping过程映射机制创建目的地类,以便映射对象。使用映射创建的目的地类包括许多个Key(键)映射或基本映射。键映射是目标中字段的基本映射配置。每一字段可具有一个或更多个键映射,以定义如何从源提取值。SourceFormula(源公式)是基于来自源的字段来构建值的表达式,所述值将被映射或分配到目标。举例来说,源公式可读取为:grossAmount+commission。目标字段:netAmount。Condition(条件)是定义条件的表达式。如果结果为true,那么将执行映射。举例来说,条件可读取为:operationType=="buy"。目标键:balanceType。源公式:"debit"。有时候,应用源公式的结果并不适应目标字段。在这种情况下,应进行转换。由转化器来完成这个转化。存在4种类型的转化器:(1)Built-inConverter(内建转化器),其通过执行用户编辑的动作来完成转化。(2)DateConverter(数据转化器),用于将值从数据格式转化成另一数据格式。(3)EnumerationConverter(枚举转化器),所述转化器指定集合对。每对集合指定将转化成一个值的多个值。(4)NumericConverter(数值转化器),所述转化器指定转化类型:abs、ceil、floor和log。在Palmyra应用程序中图27详细示出Mapping转化器的过程。4.Mapping类型Mapping用来将对象(源)映射到另一对象(目标)。存在以下2种类型的映射:(1)字段到字段映射:来自源的一个字段将映射到目标中的一个字段(无表达式)。(2)丰富映射:新版本的映射,其将一个对象(源)映射到一个或更多个对象(目标)。可用公式提取源值(例如,公式可以是“firstName+lastName”)。E.对象的装载生命周期和约束模型过程图表示过程定义。使用状态图建模技术来创建过程图,在所述技术中状态图称作生命周期或自动机。稍后,工作流引擎(其是管理业务过程的有限状态自动机)管理这些状态的生命。工作流与实体相关,由状态图表示于UML中,且用户可配置生命周期。图28示出工作流引擎的示例以及如何管理系统中的状态。生命周期或自动机文件是以XML语言描述UML中定义的图形状态图的XML文件。在UML中创建图形状态图之后,Palmrya将图形状态图重新解译为XML语言,因此在构建应用程序的过程期间及之后可易于理解。在生成步骤,将过程图变换为XML文件。使用特定配置工具将这些XML文件装载到应用程序中,所述特定配置工具允许稍后对所装载的过程定义执行语法检查,并将过程定义与先前定义的Entity类绑定。绑定是将实体类分配到过程的过程。在部署应用程序之后可随时对生命周期或过程定义进行修改。然后将在生成步骤得到的最终XML文件装载到系统中,同时考虑这些修改。通常通过UMLDesigner接口修改,以便利用内建验证能力。生成器可经配置以仅导出XML文件。约束模型是定义称作约束类的特定Entity类的类型的类图。约束模型向定义为Constrainable的先前存在的类的类型添加约束。约束是基于现有实体类在UML中定义的附加完整性规则;所述约束随后在生成步骤转化成XML文件。所生成的应用程序提供工具来将表示约束模型的XML文件装载到应用程序中。在部署应用程序之后可随时进行约束的修改或添加新约束。然后将最终XML文件装载到系统中,同时考虑这些修改。F.TraceConfiguration(跟踪配置)所生成的应用程序提供向服务器机器上创建的特定文件写入跟踪的功能性。有必要分析应用程序完成的任务且有必要对bug(错误)或技术问题记录日志时使用跟踪。TraceConfiguration还可记录业务日志和模块特定日志。应用程序提供配置工具来决定将生成用来存储跟踪的文件的位置、大小和名称。应用程序还能在所生成的跟踪中从预定的等级的细节列表进行选择。G.报告Reporting工具对于处理数据的企业应用程序至关重要。Reporting工具使得用户能够依据给定的某个标准在工作日动态生成报告。Report模块是定义和生成报告的Palmyra工具。Report模块提供简单易用的用户接口来构建Reports(“templates(模板)”),其稍后可用来生成不同格式的Reports。所生成的应用程序提供使用输入到应用程序的日期来创建Reports的功能性。ReportWriter(报告编写器)是呈现服务的部分。Report的定义基于Metadata(元数据),其说明将用作数据容器的实体类的类型和将在生成Report时输入以便选择合适对象的参数。Metadata是装载在应用程序存储器中的数据的定义。Metadata衍生自XML文件(例如,过程和约束)、所生成的代码、所写入的代码很先前存在的库。基于数据和表单定义生成呈PDF或HTML或RTF之类的多种格式的报告。Report设计器可定义标准中使用的一些参数。这些参数的值仅在Report生成之前提供。这些参数是收集数据来生成Report时应用的可选条件集合。举例来说,如果用户只想要25岁以上的Employee(雇员)的个人信息,那么他可以定义搜索标准来定制Report的生成数据。Report还可定义实体,其是表示待显示实体的主类型(类)的名称。举例来说,如果用户想要构建包括Employee的个人信息的Report,那么主Entity(实体)将是Employees。Report可定义待在Report中显示的主Entity的属性(字段)的名称,例如,employeefirstname(雇员的姓)。此外,还可对这些字段进行分组、排序,且以许多不同方式显示,诸如图表。最后,Palmyra系统还提供通过提供多种生成和修改程序员藉以工作的接口的方法来提供以可编程方式生成报告的能力。表12示出PalmyraReportingTool以可编程方式展示以工作时带有报告工具的方法的示例。Report包括任何应用程序的关键部分。然而,Report的设计可能费事费力。此外,对Report设计的任何简单修改可能会引起应用程序停止运行并要求重启。出于上述原因,Palmyra具有促进用户的Report设计过程的XSLEditorTool。这个工具允许多种设计功能性,诸如,修改报告的布局、添加动态数据、修改标签、添加表达式以及向设计添加图象。最后,Report写入工具还提供方法以图格式呈现数据。Palmyra系统含有图表库。这个库是基于Java的图表,其使得用户能够向java应用程序和网页添加图表。库含有基于AWT的图表组件、小程序和图表小服务程序(servlet)。图29示出报告生成步骤。表12:PalmyraReportingTool以可编程方式展示利用报告工具进行工作的方法的示例报告生成的示例FileOutputStreamoutput=newFileOutputStream("D:\\Report.pdf");StringreportName="myReport";CollectionValueparameters=newCollectionValue();parameters.set("parameterName",newStringValue(″testParameter"));Stringcriteria="(y1==\"testcriteria\")δ:(x1=={parameterName})";ReportGeneratorreportGenerator=newReportGenerator();reportGenerator.generateReport(output,reportName,parameters,newIODriverDefaultConfig(),criteria);报告导出动作的示例报告下载控制器的示例VI.测试A.自动测试基于应用程序的Palmyra可含有用来确保通过迭代方法添加新功能性时应用程序中无回归的测试工具。通常,回归是预建构功能性的错误,其将在生成新代码后浮现。这个工具称作Autotest,且用来记录测试脚本,手动创建测试步骤、脚本和套件,稍后运行,且比较结果。这个工具通过保证先前版本的应用程序中创建的功能仍可在增建之后工作来确保所生成的应用程序中无回归。这个工具有助于便捷地精确发现已发布测试的版本与已完成记录的版本之间在过程结果上的异常或不同。1.AutoTest(自动测试)术语StepTest(步骤测试):是AutoTest中的核心项,且呈现您想要测试的服务。ScriptTest(脚本测试):呈现程序给定案例的测试情境。脚本由排序步骤的集合构成。ScriptTest可具有其自身的InitialState。Suite(套件):如果您有多个情境要测试,那么您可将这些情况在一个套件上按序构成。Suite可具有其自身的InitialState。InitialeState(初始状态):保存在xml文件中的数据库状态的图象,由用户创建。TestMessage(测试消息):供AutoTest用来创建适合Palmyra消息的配置,所述Palmyra消息呈现待测试服务。TestMessage由服务名称、动作名称和参数组成。Result(结果):TestStep的执行结果。StepExpression(步骤表达式):用来评估结果的Palmyra表达式。TestSearchResult(测试搜索结果):使得您能够在数据库中查找并显示Result(结果)。TestCollectionSearchResult(测试集合搜索结果):如果Result是值的集合且测试是否成功取决于这些值的个数,那么在TestCollectionSearchResult中输入预期的个数。TestFailure(测试失败):每当先前测试(StepExpression、TestSearchResult、TestCollectionSearchResult)中的一个失败,且如果TestStep或TestScript运行失败,那么将创建新的TestFailure来通知失败。2.使用Autotest手动创建TestStep、TestScript以及TestSuite测试情境可编组为包括测试脚本的测试套件,而测试脚本还包括测试测试步骤。创建手动测试情境的第一步是创建测试步骤。AutoTest为StepCreation提供下拉菜单。为了查找旧Step或创建新Step,单击菜单AutoTest中的链接Step,然后单击按钮New来创建新Step。填入Step名称,且这个名称针对所有步骤是唯一的。现在创建TestMessage,这个字段是强制的,且呈现您想要测试的服务。因此您必须为这个消息选择服务名称、动作名称和用户名称。如果消息需要参数,那么您可以通过单击选项卡(tab)Parameters来创建参数,且选择可用参数类型中的一种。从组合框选择SimpleParameter来为您的消息创建simple参数,然后选择参数名称和类型,并填入参数的PalmyraValue,这个值是运行时实际参数值。如果参数值不是simple值,那么从组合框选择CompositeParameter。这样一来,您能给选择组合值且将其用作这个参数的值。用户可在两个选项之间选择,从而获得这个值。-单击链接SelectValue(选择值),并设置类的类型和搜索标准,其将用来搜索参数值。-单击链接CreateValue(创建值),并设置类的类型和草稿代码,其将用来搜索草稿值中的参数值。当您需要组合值的集合时,仅需使用CollectionParameter(集合参数)。StepExpression(步骤表达式)用来确保结果是正确的。-ExpressionName(表达式名称):针对所有StepExpression是唯一的。-ExpressionValue(表达式值):是Palmyra表达式。填入TestSearchResult名称(唯一的)、ClassType和标准,且TestSearchResult将从ClassType搜索值。TestCollectionSearchResult用来检查结果的个数,以及设定类的类、搜索所使用的标准和值的预期个数。AutoTest还为TestScriptCreation提供下拉菜单。为了查找旧Script(脚本)或创建新Script,单击菜单AutoTest中的链接Script,然后单击按钮New来创建新Script。填入ScriptName(脚本名称),且从组合框(可选)选择ScriptState(脚本状态),且Script可以或不可具有其自身的State。a.经由选项卡StepOrders(步骤次序)向ScriptTest添加TestSteps(测试步骤)更改Script内的Steps的次序很重要,因为依据这个次序来执行第一步直到最后一步。幸运的是,您可以使用链接arc随时更改这个次序。AutoTest还为TestSuitecreation提供下拉菜单。为了查找旧Suite或创建新Suite,单击菜单AutoTest中的链接Suite,然后单击按钮New来创建新Suite。填入SuiteName,且从组合框(可选)选择SuiteState,且Suite可以或不可具有其自身的State。b.经由选项卡StepOrders向TestSuite添加TestScripts更改Suite内的Scripts的次序很重要,因为依据这个次序来执行第一个Script直到最后一个Script。您可以便捷地使用链接arc随时更改这个次序。3.运行TestSteps、TestScripts和TestSuitesAutotest能给运行预先记录或创建的TestScript、TestStep和TestSuite,这是通过将用户输入手动模拟到应用程序中并比较所生成的结果与所记录的等效值来完成。提供特定设计的用户接口来执行TestSteps、TestScripts和TestSuites。Autotest生成含有已获得结果与已记录结果之间的所有不同(如果存在)的报告。然后使用报告来分析潜在异常。在分析结果并进行必要校正之后,应用程序开发人员可在结果不同是由于新版本的增强特征的情况下决定更新测试脚本。Autotest使得通过模拟用户输入和重新记录结果来自动更新已记录脚本的成为可能。运行测试步骤、脚本或套件像运行步骤一样简单,就像体验3个阶段的游戏一样:搜索;选择;以及运行4.AutoTestRecorder(AutoTest记录器)AutoTestRecorder提供简单快捷的方式来创建ScriptTests。AutoTestRecorder缺省记录与Palmyra服务不同的所有服务。但在您甚至可能需要记录PalmyraServices的一些情况下,您可以通过向配置文件添加PalmyraServices名称来轻松地实现对PalmyraServices的记录。AutoTestRecorder已含有一些条目,以下示出您如何添加更多:com.palmyra.arch.lifeCycle.adapter.manager.LifeCycleExecuter=fireEvent,fireEventWithoutconfigcom.palmyra.arch.scheduler.ctrl.JobEntryExeController=immediateExecuteJobEntrycom.palmyr.arch.persistence.entitymanager=synchronizeRecorderMenu(记录器菜单):单击菜单AutoTest中的链接Record:然后您可以在仅记录ScriptTest,或ScriptTest以及其RecordResults.之间选择。Startrecordingscenarios(开始记录情境):输入Script和Step的前缀名称(可选,如果您不选择,将使用缺省前缀名称),然后单击按钮Recording(记录),且等待直到接收到确认消息。Playtestscenario(播放测试情境):现在您可以播放您预先准备的情境。StopRecording(停止记录):完成您的情境时,停止Recorder。StartRecordingscenariosandresults(开始记录情境和结果):在开始记录之前您可能需要了解RecordResult(记录结果)。RecordResult呈现运行情境期间所使用的实体,在这种情况下,记录器散列应被同步到字符串中的每一实体,然后再次运行同一ScriptTest,AutoTest比较这些存储的散列与运行时计算的散列。您可以通过向记录器分配RecordConfig来从所散列的实体中排除一些字段。(参照下段来了解如何创建RecordConfig(记录配置))CreateRecordConfig(创建记录配置):在菜单AutoTest中选择CreateRecordConfig。输入唯一的名称。选择实体来排除它的一些键。然后,选择您想要从选定实体的散列中排除的键。5.ScriptDelete(脚本删除)ScriptDelete的主要目的是将数据库回滚到先前状态,以便了解您为何在一些情境中可能需要这个特征。-Thescenario-tobetested(待测试情境)-在数据库中创建并保存实体(City(城市))的新实例;城市名称通常是巴黎(Paris)。-动作名称是(createCity()),其没有输入参数。-(City)有两个字段,名称(name)和序列id(number),从1000开始。-您第一次成功记录情境时,新城市将添加到数据库中。PK_Name_Number_28052008Paris1000-如果您尝试运行所记录的情境,那么您肯定会获得错误消息。消息通知您,数据库中已经存在名称为相同唯一名称(Paris)的城市。-如果您以某种方式将数据库中的城市名称更改为像(London)这样的另一个名称,并运行所记录的情境,那么AutoTest就将在日志中报告错误,因为AutoTest预期(number==1000),但运行是获得的是(number==1001)。发生这种情况是因为序列字段是自动增加的。这是您需要ScriptDelete功能性的典型示例,因为您必须在运行情境之前从数据库删除旧城市并且将字段(number)的序列值重设为(1000)。可依据DeleteConfiguration(删除配置)来生成脚本删除,所述DeleteConfiguration含有待删除的类列表和待删除的序列列表。这些类的列表在ClassConfiguration(类配置)和PackageConfiguration(包配置)中指定。在配置包的过程中,您可以指定排除类的列表。序列列表在sequenceConfiguration(序列配置)中指定。为了删除类,执行以下步骤:使用Persistence(持久性)层中的“volumeDeleteSimulation”服务来执行deletesimulation(删除模拟)。这个方法并不删除值,且仅仅是删除操作的模拟。这个方法的输出是“DeletedObject”对象的集合。一个“DeletedObject”对象由className、valuePk和“Deletederror”对象的集合来定义。如果删除(错误)期间存在问题,那么这个动作将不停止模拟,但创建“Deletederror”并将其与引起这个错误的当前DeletedObject相关联。在Deletederrors的个数小于1000的情况下,Deletederror的类型为“DeletederrorPK”。否则,Deletederror的类型为“DeletedErrorCriterion”。检查删除模拟错误:验证删除错误列表中指定的所有实例都在删除对象列表中。使用删除对象和删除错误的列表来创建脚本删除。执行脚本删除。依据当前删除配置所附加的序列配置中的指定序列值来更新数据库中的序列。CreateScriptDelete(创建脚本删除):单击菜单AutoTest中的链接(SearchDeleteConfig(搜索删除配置)):-单击New-键入ScriptDelete名称,其应是唯一的-运行这个ScriptDelete时选择待删除的实体(City)。-运行这个ScriptDelete时选择序列(number)并将其值重设为(1000)-返回并保存。RunScriptDelete(运行脚本删除):为了运行任何ScriptDelete,单击菜单AutoTest中的相同链接(SearchDeleteConfig),搜索、选择和运行。AttachScriptDeletetoScriptTest(将脚本删除附加到脚本测试):现在您知道您必须就在运行已记录情境(创建Ciry())之前运行ScriptDelete(Delete-City)。AutoTest向您提供将ScriptDelete附加到ScriptTest的功能性。这可通过编辑您的脚本并向其分配所要的ScriptDelete来轻松地完成。-搜索并编辑您的ScriptTest-附加所需要的ScriptDelete当您已经将ScriptDelete附加到ScriptTest时,您无需单独运行其中的每一个,您只要运行本文档上文所示的ScriptTest。6.ChecktheResults(检查结果)为了比较并提供所记录结果与当前测试结果之间的不同,Autotest比较两个结果的hash代码。值的hash代码是依据其字符串显示来创建的。这个下显示类似于key1=val1&key2=val2,其中key1和key2是带有值的键,且val1和val2分别是key1和key2的值。所记录结果与当前测试结果之间的不同是具有不同值的键的列表。注意:用来创建值的字符串显示的键列表是简单的技术性键,其排除了序列和pk代码字段、外来pk字段、序列字段和RecordResultConfig中的测试器所指定的已排除hash键。检查测试结果的最好方法是查阅AutoTest日志文件。您可以查找文件夹“autotestLogs”中的日志文件,日志文件的名称形式是:-针对Step的名称为:“step_step-nameexecution-date.log”。-针对Script的名称为:“script_script-nameexecution-date.log”。-针对Suite的名称为:“suitesuite-nameexecution-date.log”。同样,如果您运行Step,并且出现了失败消息,那么您可以通过点击选项卡Failures来检查失败原因。7.AutotestImportExport(Autotest导入导出)存在一组有助于您导入和导出完成您的测试所需要的数据的实用工具,且您可以在主菜单AutoTest中轻松地访问这些工具。ExportDraft(导出草稿):AutoTest使得您能够将值保存在.xml文件中作为草稿,然后您可以在测试时使用这个草稿值,且您可以在两个选项中选择。ExportnewDraft(导出新草稿):按下按钮“New”来依据文本框“ClassType(类的类型)”中指定的类型创建新值。AutoTest如下导出新值到.xml文件中:-Classtype:com....City-由两个字段来呈现City类代码(名称和创建日期)-文件名称变为F:$/drafts/ClassName_ClassCode.xml。例如:$/drafts/City_Paris_01072006.xmlExportexistsDraft(导出存在草稿):选择结果中的一个,然后按下按钮“Export(导出)”,选定结果将从数据库中删除。8.AutoTest的Unittest(单元测试)为了测试您的应用程序的方法,您可以使用单元测试案例。实际上,通过使用这个案例,您可以用已传递参数运行方法,显示结果和失败值,保存配置,然后在成功执行方法的情况下进行测试,否则不测试。为了添加UnitTest配置,您必须遵循以下步骤:-在路径“AutoTest\UnitTest”下的菜单中选择动作creat(创建)。-向配置添加名称、服务名称、动作名称、用户名称和参数值。-单击按钮Run(运行)来运行方法;结果或失败将会被添加。最后,您可用预期结果或预期失败保存配置。在运行方法之后,您可查询结果。然后为了测试方法,您仅需要单击按钮Test(测试)。9.AutoTestReport(AutoTest报告)AutoTest针对每一运行情境生成报告,且报告含有成功过程的成功消息和AutoTest在错误过程执行期间侦测到的错误消息。可在应用程序的工作目录和以下路径下找到日志文件:.../WorkingDirectory/AutoTestautotestLogs报告消息:实质上,在运行情境后,可在AutoTest报告中找到3种消息,其中2种,也就是成功和警告消息是好消息并且会令您开心,然而第3种消息,也就是失败消息是更好的消息并且会令您更开心。为什么失败消息是更好的消息呢?失败消息意味着发现了看不见的错误,打算解决这个错误(这是AutoTest工具的主要目标),并且在所测试的应用程序中定位这些错误。10.DebugMode(调试模式)这个段落展示如何打开/关闭AutoTest调试模式,然后如何读取所得的调试日志。何时需要?-在大多数失败情况下,不需要调试模式。因为正常的AutoTest日志将引导您解决失败的起因,但在极特殊情况下正常日志不充分。-在这些极少数情况下,检查人员需要知道记录和运行时都发生了什么,因此出现了调试模式这个角色,调试模式向检查人员提供2个日志文件来进行比较,并解决失败的原因。-实际上,您可能需要使用调试模式的已知情况是您在正常日志中获得这个错误的情况。步骤ADJU_EMISSIONS_fireEvent_1207239411130已失败[[ExecuteThread:'12'forqueue:'weblogic.kernel.Default'][711833142]]错误:这个同步中的记录结果的类型应为[X],而运行时找到的类型是[Y]。DebugmodeOn/Off(调试模式打开/关闭):如果想要在AutoTest中打开调试模式,那么向以下路径添加文件(debug.mode):../AutoTest/debug/debug.mode为了关闭调试模式,您必须删除或重命名这个文件(debug.mode)。Debugmodeusage(调试模式使用):应遵循以下使用次序,以便获得调试模式的优势:1.打开调试模式2.记录您的情境(s1)3.运行这个情境(s1)4.关闭调试模式结果将是可在以下路径找到的许多个日志文件:../AutoTest/debug/step1_record_uniqueNum.logstep1_run_uniqueNum.logstep2_record_uniqueNum.logstep2_run_uniqucNum.logDebugmodelogs(调试模式日志):调试模式的额外结果(除了已记录脚本)是调试日志文件。大多数已记录步骤具有2个调试日志,一个是记录时间的日志,而另一个是运行时间的日子。您可以通过名称来区分这2个日志:../AutoTest/debug/step1_record_uiqueNum.log(在记录时间)step1_run_uniqueNum.log(运行时间)VII.最终应用程序的结构(Palmyra框架)A.呈现层1.层的设计a.选定架构出于许多原因(包括安全性、可维护性和处理的集中性),选择了瘦客户端架构。在这个架构中,软件系统被分成至少3层。以下是3层中每一层的简要描述:thin-client(瘦客户端):瘦客户端是与终端用户直接交互的层。薄是因为根本不含业务逻辑。瘦客户端仅提供与用户通信的方式,且由用户安装于每台机器上。作为产品,瘦客户端可以是完整软件解决方案的步伐,或是诸如web浏览器的第三方产品。presentationtier(呈现层):这一层在服务器侧运行。这一层经由一些网络协议与瘦客户端通信。这一层知道如何将请求委托给适合服务,以及如何通过向瘦客户端发回响应来显示结果。这一层还使得用户能够从一个案例跳转至另一案例。businesslogictier(业务逻辑层):仅在这个业务逻辑中执行应用程序的业务逻辑。业务逻辑层可被视为相互调用、被呈现层调用以及知道需要处理已存储数据时如何连接到数据库的许多个服务。前面2个层都是与呈现模块相关的层,且将在本文档下文中着重描述这2个层。b.选定设计模式MVC2(代表Model、View和Controller)设计模式是经过证明对具有先前说明的架构的应用程序很实用的设计模式,其中应用程序分成以下3种组件:Model(模型):模型提供用来访问数据库(或应用程序的状态)以及运行业务过程的一组服务。View(视图):知道如何针对每一可能案例建构用户接口的一组组件。Controller(控制器):从客户端接收请求并向其发回响应的组件。控制器知道如何将这些请求转为内部请求,以及如何将这些请求委托给模型中的适合服务。控制器还知道如何选择将建构用户接口的适合视图组件c.控制器的详述在MVC2设计模式中,明显的是,控制器组件仅负责与瘦客户端通信,因此,应了解将控制器组件连接到瘦客户端的网络协议,并且还应了解瘦客户端的语言,这样才能解译瘦客户端的请求,并向其同步回响应。因此,我们期望实施控制器构建的大部分代码是依赖于客户端的。另一方面,控制器还负责将请求委托给模型中的适合服务,且负责选择讲决定响应内容的视图组件。这个功能性与瘦客户端的类型毫无关系。因此,控制器组件可被视为以下两个单元的联合:PresentationPort(呈现端口):客户端可藉以连接到应用程序的呈现层的唯一单元。呈现端口知道与瘦客户端的通信相关的所有技术细节。PresentationController(呈现控制器):这个单元用来从呈现端口接收独立于客户端的请求,将处理委托给适合服务,选择适合的视图组件,以及向呈现端口发回独立于客户端的响应。图48显示呈现层可如何得益于其设计而支持许多种技术。d.BigPicture(大图)通常,用户与程序模块之间的交互始于使用一些瘦客户端向“监听”客户端的呈现端口发送请求。这个请求是依赖于客户端的,且呈现端口必须将其转化为独立于客户端的请求。一旦完成,呈现端口将这个请求转发给呈现控制器,其将执行必要动作来处理这个请求。一旦处理完请求,呈现控制器现在可进行响应。响应必须呈新图形用户接口的形式,或已显示接口的更新。控制器应知道待渲染或更新的图形组件以及待绑定到这些组件的值。然而,因为呈现控制器并不知道如何与瘦客户端通信,它需要通过呈现端口本身来与瘦客户端通信,而呈现端口必须向呈现控制器提供用来渲染用户接口的方法。因此,当呈现端口调用呈现控制器来构建用户接口时,它应传递呈现控制器将用来在用户接口上渲染组件的对象(Renderer,渲染器)。显示在用户接口上的组件通常是对当前会话中的值的图形显示。当呈现端口由于用户与显示接口之间的交互而接收请求时,端口知道被更新的图形组件,但并不知道如何更新这些组件表示的值。因此,Renderer还是呈现控制器将对象(ValueBindings,数据绑定)传递到呈现端口的一种方法,以使得有助于呈现端口从构建的用户接口接收请求时更改会话中的值。为了避免一个用户接口的会话数据覆写另一个用户接口的会话数据,每一用户接口(或页面)必须在会话中具有其自身的存储器空间。我们将这些独立空间称作PageData(页面数据)。呈现控制器是知道如何创建、初始胡和更新PageData对象的构建,但呈现端口知道如何在保持呈现控制器在会话中返回的PageData对象,以及如何将这个PageData对象与渲染页面(或用户接口)相关联。当然,为了遵循MVC2设计模式,呈现控制器自身不应处理从呈现端口接收到的请求,也不应构建页面,尽管从呈现端口的角度来看,这些看起来都是呈现控制器在做。相反,呈现控制器应定位将处理所接收的请求或动作的合适服务。此后我们将这个服务称作ActionHandler(动作处理器)。类似的是,当查看或渲染页面时,呈现控制器必须定位合适的视图组件或ViewBuilder(视图构建器),其知道如何渲染页面,并调用然后传递到Renderer(渲染方)对象。图49示出上述示例的图示。e.呈现端口的提取为了提取呈现端口,我们必须定义在呈现端口与呈现控制器之间通信的语言。这种语言可表达出在两个单元之间交换的对象。以下是这些对象的列表:Request(请求):请求含有客户端发送任何数据。这个数据包括目标页面或待开始的案例,以及影响业务逻辑的执行的附加参数。这个对象的接口必须在呈现控制器中宣称,且每一呈现端口应提供其自身对那个接口的实施。实施将很有可能包装依赖于客户端的请求。PageData(页面数据):这个对象表示为每一显示页面保留的会话空间。因此必须存储在会话中。这个对象应使用唯一标识符来识别,因此它可在稍后的请求响应中加以引用。Session(会话):与请求包装特定于客户端的请求极其相似,会话也包装特定于客户端的会话。必须在呈现控制器中宣称的这个对象的接口仅含有向会话添加PageData对象和从会话去除PageData对象的必要方法。Renderer(渲染器):这个对象的接口(必须在呈现控制器中宣称)定义任何呈现端口应知道如何构建的一组组件。每一呈现端口必须提供其自身对那个接口的实施。ValueBinding(值绑定):当ViewBuilder(视图构建器)调用Renderer来构建用户接口时,ViewBuilder应将它传递到这个类的实例,以便指定每一可视组件如何映射到PageData中的值。可稍后经由呈现端口来使用这些ValueBinding对象,以便更新PageData中的值(例如,接收到新请求时)。f.装载合适动作处理器/视图构建器在请求处理的传统方法中,控制器读取请求中的参数,然后其运行一连串if-else(如果-否则)语句(和嵌套的if-else语句),所述语句将最终使得正确的动作得以实施。这种方法中的控制器代码难以维护。因为必须添加新动作(其处理特殊请求),然后必须修改一连串if-else语句,这样一来可能会引入错误。更好的方法是使用寄存器/工厂(factory)设计模式。这种方法中的动作将其自身寄存到工厂处。当控制器接收到请求时,其查找工厂中对这个请求感兴趣的动作。使用键对象来完成寄存和查找操作。这个键可以由请求中的数据和会话中的相关数据来创建。视图构建器必须以相同方式定位。g.对上下文的需要假定用户接口含有按钮“Save(保存)”,且用户单击按钮“Save”。在这种情况下,呈现控制器将接收到告知必须完成“Save”动作的请求。呈现控制器将查找针对这个动作寄存的处理器并调动这个处理器。这是最简单的可能出现的情况,且从这个情况,我们推断出查找操作中使用的键是与被按压下的按钮相关联的动作名称。然而,这还不够,针对动作“Save”寄存的动作处理器将处理所有“Save”动作,而不管源按钮存在于哪一页面。这意味着呈现控制器需要知道事件藉以发生的精确上下文。i.定义上下文实际上,任何用户接口都是系统中一个实体的可视化表示,且系统中的每一实体是一些类型的实例。用户执行的动作(诸如,“Save”动作)可依据实体类型而以不同方式处理。这意味着页面显示的实体类型是上下文的一部分。另外,与任何页面的交互实际上是以下已知案例中的一个的特殊情况。Edit(编辑):用户创建新实体或更新已有实体的案例。View(视图):用户检查已创建实体的案例。SearchInput(搜索输入):在这个案例中,用户指定其藉以搜索实体的搜索标准。Search(搜索):在这个案例中,用户显示他/她找到的满足在搜索输入案例中指定的标准的实体。在上文给出的示例中,动作“Save”是所显示实体上执行的业务动作。存在用来导航所显示实体的其他类型的动作。借助于这类动作,用户可查看与所显示实体相关的实体。还存在可源自用户接口的其他类型的动作。这类动作的示例是修改一个组件时刷新页面或其组件内容的动作。总的来说,可使用以下属性来定义上下文:用户名称。实体类型。动作类型(可视化动作、技术动作、导航、刷新、轻量刷新)。说明动作名称、导航角色或所修改组件(视动作类型而定)的参数。ii.更多精确上下文上述上下文是可能在一些情况下不充分的简单上下文。一般来说,我们需要知道动作藉以执行的精确上下文。精确上下文是依据当前页面的简单上下文和调用方页面的精确上下文而定义。调用方页面是用户藉以访问当前页面的页面。图50示出动作如何从给定上下文的工厂获取动作。h.超动作处理器/视图构建器缺省情况下,呈现模块将针对最一般和熟悉的案例寄存基础动作和视图构建器。举例来说,针对以下上下文:案例:Edit(编辑)实体类型:任何类型(例如,CompositeValue)。动作类型:Action。参数:Save。我们将找到调用方法“synchronize”的寄存的缺省动作处理器。假定一个请求具有以下稍有不同的上下文:案例:Edit实体类型:Currency(货币)(CompositeValue的子类)。动作类型:Action。参数:Save。尽管上下文不同,但是,由于没有动作处理器寄存这种情况,因此呈现控制器应选择“SuperActionHandler(超动作处理器)”,其是针对最一般情况寄存的处理器(例如,缺省动作处理器)。i.动作处理器接口系统中的每一动作处理器必须实施接口com.palmyra.arch.presentation.actions.ActionHandler:这个接口具有4种方法,其中最重要的1种方法是executeAction(执行动作),且其角色是执行与这个动作相关的业务逻辑。这个方法具有以下3个参数:(1)Request(请求)。请求含有客户端发送任何数据。这个数据包括目标页面或待开始的案例,以及影响业务逻辑的执行的附加参数。这个对象的接口必须在呈现控制器中宣称。(2)SuperActionHandler(超动作处理器)。开发人员时常需要扩展特殊案例的动作处理功能性。这意味着开发人员必须从他/她的动作处理器调用超动作处理器。在并不知道并扩展超动作处理器的实际类型的情况下,动作处理器的接口必须允许传递特殊对象(具有类似于动作处理器接口的接口),藉此可调用超动作处理器。这样一来,开发人员就无需知道超动作处理器的实际类型,或如何定位超动作处理器。相同技术必须与视图构建器一起使用。(3)PageData(页面数据)。明显的是,页面数据是输入到将处理用户请求的业务服务的输入。由于这个数据保留PageData对象(其是目的地为所显示页面的会话空间)中,那么应这个对象传递到动作处理器。(4)TargetInformation(目标信息)。在执行动作之后,呈现控制器将进行以下操作中的一个,且动作处理器将通过保持TargetInformation对象来负责告知程序控制器接下来做什么:Callinganewpage(调用新页面):在这种情况下,动作处理器必须在其结构中指定所调用页面的上下文(包括调用之后将执行的动作)、将传递到所调用页面的数据,以及从所调用页面返回之后将执行的动作。Forwardingtoanewpage(转发到新页面):类似于前一情况,仅仅是所调用页面无法返回到调用方页面,且因此无需指定返回之后将执行动作。Stayinginthesamepage(停留在同一页面):这个操作允许执行另一动作而并不将控制传输到另一页面。在TargetInformation对象的简单上下文中查找这个动作类型和名称。Returningtoacallerpage(返回调用方页面):动作处理器必须指定待返回到调用方页面的数据。Noneofthepreviousoperations(非以上操作中的任何一个)。因此,TargetInformation对象必须含有以下属性:NavigationType(导航类型):可以是Call(调用)、Forward(前进)、Stay(停留)、Return(返回)或None(没有)。TargetContext(目标上下文):用于NavigationType是Call或Forward的情况。UseCaseConfiguration(案例配置):将传递到所调用页面(举例来说,待检查的值)的配置。TheOn-ReturnAction(返回动作):从所调用页面返回之后将执行的动作的名称。TheOn-ReturnActionType(返回动作类型):从所调用页面返回之后将执行的动作的类型。表1是Presentation(呈现)通用动作处理器ActionSave(动作保存)的示例。表1:Presentation通用动作处理器ActionSave的示例j.视图构建器接口通常,当页面调用另一页面时,所调用页面必须渲染在调用方页面内部。为了允许这么抽象,视图构建器必须具有以下方法:buildView(构建视图):呈现控制器将在调用调用方页面的视图构建器内嵌套调用页面的视图构建器。以下是任何视图构建器的输入:PageData(页面数据):页面数据必须含有将由视图构建器可视化呈现的数据。Render(渲染器):呈现端口提供的这个对象用来辅助呈现控制器渲染可视化用户接口。Request(请求):有时候,呈现控制器可以决定仅必须更新一些页面而无需渲染全部页面。出于这个原因,视图构建器含有在这种情况下使用的以下方法很实用:updateKeys(更新键):updateKeys方法必须返回待更新的组件列表。这是视图构建器接口的示例。*返回要更新的组件集合。k.PageData(页面数据)如上文所提到的,页面数据是为每一显示页面或用户接口保留的会话空间。PageData对象具有用来访问会话中的页面数据的标识符。这些标识符还用来将所渲染表单绑定到其对应的PageData对象。然而,一旦定位PageData对象,必须恢复页面的上下文,以使得呈现控制器可定位将在所找到的PageData对象上操作的合适动作处理器。恢复上下文的最好方法是将其保持在PageData对象本身内。另外,因为页面彼此调用,且因为这些必须渲染在表示完整案例的同一帧中,所以让每一PageData对象保持对的调用方页面所对应的PageData对象的引用很实用。这样一来,PageData对象不再需要保持其完整的上下文。相反,PageData对象仅需要保持简单上下文(例如,案例名称、类名称、动作类型和参数)。上下文的其余信息可在调用方页面的Data对象中找到。实际上,如果我们从Context对象衍生接口,PageData对象可视为这个接口的实施例。l.呈现控制器如何工作当呈现控制器接收到请求时,这个请求将发起新案例,或是已发起案例的部分。在前一情况下,请求必须含有待发起案例的简单上下文。在后一情况下,请求必须提供对目标PageData对象的引用和关于待执行动作的信息。当发起新案例时,呈现控制器必须创建PageData对象,并通过将上下文信息复制到其来初始化。对于已发起案例的情况,呈现控制器仅必须将关于待执行动作的信息复制到PageData对象。这实际上将修改PageDate对象的上下文。在两种情况下,呈现控制器必须定位并调用适合ActionHandler对象。ActionHandler对象将返回TargetInformation对象,其确定呈现控制器下一步应做什么。动作处理器可决定调用新案例,且因此必须建构新PageDate对象并将其链接到调用案例的PageDate对象,且必须调用新ActionHandler。这意味着呈现控制器将进入当最后被调用的ActionHandler决定不应再执行任何动作时中断的循环。2.GUI(图形用户接口)所生成的应用程序自动提供基于web的用户接口。自动化UI(用户接口)生成过程将元数据(包括类和过程)用作可实施为HTML页面或本地屏幕库的输入和输出可视元素。所生成的页面是创建新对象、搜索已创建对象和编辑或删除对象的基本案例。Palmyra框架自动生成用来创建、编辑和搜索Entity类的类型的屏幕页面,所述类型在目标应用程序的UML模型中定义。通过使用生成屏幕的缺省布局的算法,依据实体类的字段和关系来生成屏幕内容。算法基于类的结构来生成布局,然后可稍后视需要使用视图格式工具来重新分配可视元素。可稍后使用View格式配置工具来手动修改表示字段和关系的可视元素(文本框、组合框、列表、链接)的使用及其在屏幕上的分布。可在运行使用View格式配置工具来修改用户接口。自动生成的屏幕页面含有用来启动Save或Delete或Search这类动作的一组预定的按钮。过程相关的动作(过程图中定义)也在目标应用程序中自动生成。当使用案例转换图定义目标应用程序中的案例时,还可向页面添加特定动作。当添加特定动作时,手动编写动作相关的处理,并使用UML生成工具集成到应用程序中去。当并无预定的所要的处理或依据特定需要而需要增强时,需要手动编写的代码。a.Dashboard(仪表板)同样作为图形用户接口的部分,Palmyra还向用户提供Dashboard工具。仪表板这个工具有助于每一应用程序用户知道他的“Todo(任务)”列表,且这个工具还提供关于他任务量的说明。仪表板列出用户必须执行的任务。依据每一用户的特性,每一用户有他自己的任务列表。服务提供配置接口,以便允许超用户向用户分配特性和条件。这个工具还保证了所有任务都能被分配出去。仪表板是一组节点,且每一节点含有子节点。每一节点与实体相关。实体依据仪表板的管理员所定义的条件而显示。任务类表对应于每一实体。任务是通向使得这个任务能够完成的产品案例的链接。运行时执行Dashboard的配置。3.输入和输出装置a.I/O装置输入和输出装置是机器与其他系统通信所基于的途径。框架定义输入和输出装置应遵循的模板。框架还定义支持FTP/HTTP/Queues/EmailsviaSMTP这类普通协议、打印机和传真机(作为输出装置)的一些输入和输出装置。使用消息交换来进行通信。输入装置接收由其他系统生成且将被目标应用程序读取的消息,而输出装置发送目标应用程序生成的消息。应独立于所用输入装置的通信端口和类型而对到达系统的消息进行解析,以便将信息传输到针对目标应用程序以适合方式表示的数据中。这通过两个独立模块,也就是驱动器和映射来完成。系统生成的消息还取决于映射和驱动器,以便将数据从内部表示变换成中间形式,且最终变换成消息。b.Mapping(映射)Mapping模块是基于配置的格式变换器。配置定义源类型和目标类型(目标应用程序的元数据中定义的两个实体类的类型),且定义如何将源类型的字段值变换成目标类型的字段值。使用框架所定义的表达式语言来编写变换公式。表达式使得进行算术运算或调用源元素的字段值上的预定义方法成为可能。配置还使得向映射指令添加条件成为可能,因此仅执行满足条件的指令。在应用程序部署之后完成映射配置,且配置存储在特定的数据表中。映射模块原则上用于输入和输出操作中,其中数据从内部系统表示转化成驱动器所使用的中间表示,反之亦然。c.驱动器驱动器用于从特定格式进行读取或写入成特定格式。在输入装置中,来自外部系统的消息呈XML、XLS或SWIFT这类预定义格式。将这些消息解析并转化成驱动器所定义的中间结构。在输出装置中,生成消息以便与其他系统进行通信。所生成的消息也具有预定义格式。可针对每一格式或格式类型创建驱动器。框架定义驱动器的模板。框架还针对XML、固定文本和快速(swift)消息这类的一些格式定义一组驱动器。一些驱动器需要配置,尤其是当格式比较灵活时。举例来说,XML是一种格式,但其也是一种语言,因此运行时以特定方案定义标记和元素的结构,且配置存储在特定的数据表中。C.业务层1.基本结构定义框架中的元数据的模板称作基本结构。基本结构被视为Palmyra框架的核心,因为所有Palmyra服务都要使用基本结构。,不论是借助所生成代码的元数据定义,还是使用约束模型的动态定义的元数据定义,还是借助于编写代码的元数据定义,所有元数据定义都是基于基本结构所定义的模板。借助于使用预定的模板,所有实施类型继承完整性检查、序列化、去序列化的功能性和具有自动计算字段的可能性。基本结构定义框架中所有实体的语法和基本行为。基本结构是向Java中的基本类添加新特性的一组接口和类。基本结构由用于应用程序开发的类构成。这些类是Java原语和JavaCollection(Java集合)框架的包装。a.基本结构的包主包com.palmyra.arch.basicStru.ct含有若干子包。最重要的是:com.palmyra.arch.basicStruct.data:这个子包含有框架中的简单和结构化数据类。com.palmyra.arch.basicStruct.metadata:这个子包含有描述符、元数据类、守护程序类表、完整性检查器和域管理器。com.palmyra.arch.basicStruct.exception:这个子包含有框架地址定制的异常。图33示出这个包提供的异常。com.pabnyra.arch.basicStruct.init:这个子包含有负责在启动服务器时装载所有Palmyra类的主类GeneralInitializer.java。com.palmyra.arch.basicStruct.interfaces:这个子包含有连接到框架中不同模块的接口的定义,诸如,配置、安全性、序列、跟踪、持久性、翻译器、生命周期和文件管理器。这个子包也含有每一接口的缺省实施例。com.palmyra.arch.basicStruct.io:这个子包定义可定义、配置和寄存驱动器的接口列表。b.包com.palmyra.arch.basicStruct.data这个包含有框架中的基本建构。这个包中的类是在Palmyra框架下构建应用程序所用的主数据块。这些类实施框架中的最高抽象等级的接口Value。这个接口定义所有框架对象的通用行为。接口Value规定所有实施类将Cloneable(可复制)、Comparable(可比较)和Serializable(可序列化)。另外,实施类可由适当格式化的人类可读字符串和XML文档来建构,且实施类可保存成类似字符串和XML。每一值与可用来检验这个值的定义和本质的类型Classe的元数据描述符类相关联。表13示出包com.palmyra.arch.basicStruct.data的接口Value中定义的主要方法。表13:包的接口Value中定义的主要方法c.BasicStruct(基本结构)主角色basicStruct由SimpleValue(简单值)、CollectionValue(集合值)和CompositcValue(组合值)构成。这些类型中的每一类要求特殊的规程供使用。然而,在使用所有提到的类型方面存在以下通用规则:每一Value对象具有与类型Class相关联的Classe实例,这个实例用来描述这个值且由方法getClasse提供。图32示出Classe的组合。每一Value对象具有缺省建构器,字符串参数建构器和方法setValue。这个方法提取字符串并依据这个字符串建构对象的内容。每一Value可提供呈可读取字符串格式的内容。一般来说,借助对类Value进行类的细分、创建新Classe实例并将其与Value的新类相关联来更改Value的约束。当对任何类Value进行类的细分时,用户应总是创建描述这个值的Classe的适合实例、逾越方法getClasse,且明确宣称缺省建构器。接口Value中定义的主要方法是:用于检查内容、检查完整性和检查规则的方法;用于得到有关对象元数据信息、getClasse和getField的方法;用于读取并保存呈不同格式的对象(read、write、setValue和toString)的方法;以及命名方法。图30示出包com.palmyra.arch.basicStruct.data的接口Value中定义的主要方法。d.ValueInterface(值接口)接口Value具有3种实施类。类SimpleValue是Java原语或包装类的对应部分,或者其可以仅仅是原子或简单值。类CollectionValue是同类项的集合。类CompositeValue是Java类的对应部分,或者其可以仅仅是具有不同类型的项的容器。e.SimpleValue类SimpleValue是架构中单个或原子值的抽象。这意味着这个类的实例逻辑上含有一个值。这个类的子类是Javasimple数据类型的包装。图36表示SimpleValue类型及其子类的类图。i.BooleanValue(布尔值)这个子类是包装Java布尔原语。BooleanValue不具有特殊约束或规则。表14示出BooleanValue的示例列表。表14中创建了2个BooleanValue实例。所创建的第二个BooleanValue的内容依据字符串参数设定。表14:布尔值的实施BooleanValuebvl=newBooleanValue();BooleanValuebv2=newBooleanValue("true");bvl.setValue(true);System.out.println(bvl.getValue());System.out.println(bv2);System.out.println(bv2.getClasse());ii.StringValue(字符串值)这个类是JavaString类的包装。图34B示出类StringValue的示例。StringValue向JavaString对象添加3个约束:内容字符串的最大长度、内容必须应用的平屏蔽和可能有效值的列表。这些约束保存在与StringValue对象相关联的StringCls元数据实例中,且缺省StringCls实例不具有这些约束的值。为了更改这些约束中的一个或更多个,程序员必须对StringValue进行类的细分并修改与新类相关联的StringCls实例中的这些约束,如表15所示:表15:StringValue的约束的示例packagetest;publioclassMyStringValueextendsStringValue{privatestaticfinalClassecls=newStringCls("test.MyStringValue″,newInteger(4));/*注意:我们应总是明确地宣称缺省的构造器和Classe获取器方法。*/这个代码定义具有最大长度4的新StringValue(字符串值)。我们可从与StringValue相关联的StringCls得到最大长度和其他约束。MyStringValuesv=newMyStringValue();Integermax=((StringCls)sv.getClasse()).getMax();System.out.println(max);//打印输出:4iii.DateValue(日期值)类DateValue是JavaDate类的包装。DateValue具有2个约束:最小和最大日期。表16示出如何从Date(日期)或String(字符串)参数创建DateValue对象的示例。表16:如何从Date或String参数创建DateValue对象的示例DateValuedv1=newDateValue();DateValuedv2=newDateValue("22/1/1977");dv1.setValue(newDate());System.out.println(dv1.getValue());System.out.println(dv2);iv.NumberValue(数植)抽象类NumberValue是框架中所有数值类的超类。这个值的元数据类是类NumberCls。这个类对NumberValue的内容定义2个约束:最小和最大值。另外,和在类JavaNumber中一样,这个类提供用于在多个数值类之间进行转化的方法helper。NumberValue的子类是IntegerValue(整数值)、LongValue(长整型值)、FloatValue(浮点值)和DoubleValue(双精度值)。表17示出如何从Double、Integer或String参数创建不同类型的类NumberValue的示例。表17:如何从Double(双精度值)、Integer(整数值)或String(字符串)参数创建不同类型的类NumberValue的示例NumberValuenv1=newIntegerValue();NumberValuenv2=NumberValue.newInstance(newDouble(88.421));IntegerValuenv3=newIntegerValue(nv2.asInteger());IntegerValuenv4=newIntegerValue(″1977");System.out.println(nv1);//打印输出:0System.out.println(nv2};//打印输出:88.421System.out.println(nv3};//打印输出:88System.out.println(nv4};//打印输出:1977v.DynamicStringValueClass(动态字符串值类)DynamicStringValue(动态字符串值)是可在运行时更改描述符类StringCls的StringValue。类DynamicStringValue的实例的StringCls实例可在建构器或其生命周期的任一部分中设定。表18示出DynamicStringValueClass的示例。表18:从格式化字符串创建ListValue(列表值)并向其添加项的示例f.CollectionValue(集合值)这是框架中所有容器或数据结构的超类。图31示出包com.palmyra.arch.basicStruct.data中实施的类Collection。CollectionValue的子类可以是具体实施方案或向现有具体实施方案添加特定特性的过滤器类。CollectionValue的子类包括:listValue、基于JavaList的集合实施方案;MapValue(表19),基于JavaMap的集合实施方案(表20);ConditionalCollection,基于特定条件过滤具体实施方案的内容的集合;以及PageByPageCollection,向其他实施方案添加分页行为的集合(表21)。类CollectionValue是Java中Collection概念的框架对应部分。CollectionValue是具有类型为Value的项的包装。表19:MapValueClass的示例表20:类CollectionClassValue的示例另外,我们定义了条件最后,我们将条件对象应用到丢弃ConditionalCollection(有条件集合)实例的ListValue(列表值)实例,表21:PageByPagelterator的示例类CollectionCls的实例与每一类CollectionValue相关联。CollectionCls强加给CollectionValue的唯一约束是这个项的类型。表22示出ReferencingClass(参考类)的示例。表22:ReferencingClass的示例为了远程引用这个类,我们应创建扩展类Reference(参考)的新类,且其具有与这个类相同的名称。packageremote;publicclassNewStringValueextendsReference{}g.CompositeValue(组合值)CompositeValue是含有预定的字段定义的数据结构。字段的定义存在于与每一CompositeValue对象相关联的CompositeCls实例中。这类似于由数字构成的类的概念。CompositeValue对象将其字段的定义存储在其元数据类中。CompositeValue的子类是:DynamicValue(动态值),其是可在运行时更改字段的CompositeValue;ID,其是由LongValue主键和StringValue代码成员构成的CompositeValue。图34A示出类CompositeValue的子类。类CompositeValue扩展类CollectionValue,因此所有针对CollectionValue有效的运算针对CompositeValue也有效。不同于CollectionValue,用户无法设定类CompositeCls中并未定义的键的值,仅所宣称的字段具有值。类CompositeValue在框架中的角色与类在Java中的角色相同。类CompositeValue是由预定的字段构成的结构。类CompositeValue引用定义其的元数据类CompositeCls。CompositeCls又含有元素类型为Field的集合字段。每一字段又与特定Classe类型相关联。类CompositeValue定义用来操纵其字段值的一组方法。最重要的方法如下所示:get(Stringkey):返回给定键的值。键可以是simple(a)或composite(a.b.c)。getSimple(Stringkey):返回给定simple键的值。set(Stringkey,Valuevalue):设定带有给定值的字段的值。键可以是simple或composite。类CompositeValue提供这个方法的许多重载版本。setSimple(Stringkey,Valuevalue):设定带有给定值的simple字段的值。remove(Stringkey):从存储器去除键的值。字段可以是simple或composite。removeSimple(Stringkey):从存储器去除simple键的值。isAssigned(Stringkey):如果键在存储器中具有值,那么返回true。键可以是simple或composite。isAssignedSimple(Stringkey):如果simple键在存储器中具有值,那么返回true。CompositeValue中定义的字段可呈两种状态中的一种。Assigned(已分配):如果字段在存储器中具有现有值,那么字段视为已分配。在调用两个方法set或get之后,每一字段视为已分配。Notassigned(未分配):如果字段在存储器中不具有值,那么字段视为未分配。在对字段执行去除操作之后,字段具有状态“notassigned”。图35示出创建并定义类CompositeValue的字段的示例。i.DynamicValue(动态值)DynamicValue是与非静态Classe实例相关联的CompositeValue。因此,这个类实例可在运行时进行更新,且可在运行时向这个DynamicValue对象添加字段。表23示出使用这个类的示例。表23:DynamicValueClass(动态值类)的示例首先,我们定义类DynamicValue,然后,我们创建Employee的实例,且我们在运行时向其添加字段,ii.IDclass(ID类)ID类表示针对特定AbstractValue实例的标识符或主键。ID扩展CompositeValue,且由三个字段idPk、idCode和idType构成。每一AbstractValue实例提供唯一的ID实例,pk由序列服务提供并维护,code由字段AbstractValue在运行时评估,且type呈现type实例的名称。在表24中,code是由具有其orderInCode特性组的字段组合构成的StringValue。我们从代码列表可以看出,这个类AbstractValue中定义的前3个字段的orderInCode特性设为整数值,而剩余字段的orderInCode特性设为缺省值null。因此,在这个代码的输出中,可按所述次序打印指定字段的值。表24:ID类代码的示例h.Keysclass(Key类)Key类是定义可存在于类CollectionValue或CompositeValue中的可能字段的名称的Map结构。“可能”意味着,键表示CompositeValue中定义的字段,但未必是现有字段。只要装载了对象的类,字段自身的定义存在于可从与Value的类名称相关联的Classe实例中获得的Field对象中,但运行时这个值可具有键,且因此指定字段的值可能不具有键。类Keys的结构是Map,因此Map中的每一条目具有键和值。键是含有字段名称的String对象,且值是含有这个字段的可能键或在这个字段不具有键的情况下为空值的Keys对象。框架中的3种主要类型可如下返回Keys实例:SimpleValue:始终返回null(空值)。CollectionValue:返回具有一个条目的Keys实例,所述条目中将“*”作为键,这意味着CollectionValue对象可提取任何字段名称,且这个条目的值是这个CollectionValue的项的Keys结构。CompositeValue:返回含有与这个CompositeValue实例相关联的CompositeCls对象中所定义的所有字段的Keys实例。框架使得提取与以下一组特性相关的键列表成为可能:owner(所有者)、declared(宣称)、mandatory(强制)、assigned(已分配)、relationtype(关系类型)、code(代码)、calculated(计算)等。Classe类中定义了这些方法的这组特性。i.DeepMapclass(DeepMap类)这个abstract(抽象)类是接口Value的第一实施方案。其逾越Map的缺省行为,并实施带有深度命名访问的新对象。所有CollectionValue实施方案得益于这个类,并接受composite对象名称作为键。j.AbstractValue(抽象值)AbstractValue是应用程序中所有持久性对象的超接口。AbstractValue含有用于保存和获取来自任何存储服务的AbstractValue的缺省或技术字段。技术字段有pk、type(类型)、accessPoint(接入点)、creationDate(创建日期)、creatorUserId(创建者用户Id)、updateDate(更新日期)、updatorUserId(更新者用户Id)。AbstractValue具有与持久性相关的3种方法:Synchronize(同步):告知持久性服务保存这个AbstractValue对象。Delete(删除):告知持久性服务删除这个AbstractValue对象。lazyGet(Stringkey):从应用程序存储获取字段值。k.包com.palmyra.arch.basicStruct.metadata这个包含有4个主要部分:框架中所有元素的元数据描述(简单值、组合值、集合值和控制器)、守护程序(IfAdded、IfNeeded和IfRemoved)、域管理器和完整性检查器。i.MetaDataclasses保持框架类的元数据描述的主类是Classe。框架中的每一对象与Classe对象相关联。这个实例保持关于Value的不同字段和Value自身特性的信息。这个类的主要方法如下:ValuenewInstance():创建值的新实例。ClasseforName(StringclassName):获取值的元数据描述。ClassegetSuperClasse():返回超类的元数据描述。ListgetAllImplementedlnterfaces():返回所有布植接口的名称。KeysgetSubClasses():返回所有子类的名称。Classe具有许多子类。主要子类如下:SimpleCls:是保持Simple值的类的元数据定义的根类。其主子类如下:与类型BooleanValue实例相关的BooleanCls、与类型BooleanValue实例相关的BytesCls、与类型DateValue实例的DateCls、与类型NumberValue实例相关的NumberCls、与类型StringValue实例相关的StringClB以及与类型TimeZoneValue实例相关的TimeZoneCls。CollectionCls:是保持Collection值的类的元数据定义的根类。这个类使得获得集合的项类型成为可能。CompositeCls:是保持框架中类Composite(实体和接口)的元数据定义的根类。其主要方法如下:FieldgetField(Stringname):返回字段的元数据描述。ListgetCodeFields():返回标记为代码的字段列表。KeysgetKeys():返回所有字段的名称。CompositeCls定义这个方法的许多重载版本。KeysgetDeclatedKeys():仅返回所宣称的键。KeysgetOverriddenKeys:仅返回所逾越的键。注意:所有键=所宣称的键+所逾越的键。CompositeCls具有许多子类:AVCls:与扩展CompositeValue和实施AbstractValue的每一类或扩展AbstractValue的每一接口相关。ConstraintableCls:与UML模型中Stereotype为“consttaintable”的类相关;InterfaceCls:与扩展接口Value的每一接口相关。DynamicCls:与动态值的类相关。ConstraintsCls:是DynamicCls的子类,与UML模型中标记为“constraints”的类相关。类Field是元数据描述的基本对象。每一CompositeCls实例保持Field实例的组。每一CompositeCls实例描述带有另一类的属性或惯性。使用如下一组特性来定义字段:name、Classe(等效于type)、最小和最大多样性、集合类型(映射、组或列表)、关系类型(Simple、composition、aggregation或association)、owner(所有者)、navigable(可导航)、transient(暂态)等。类Classe–Field用来描述带有其字段的值。然而,使用类Controller、Method和Patameter来描述控制器和方法的元数据。Controller是描述用户定义的服务(或控制器)的元数据。Controller提供方法来访问名称、别名、超控制器、所宣称方法、所有方法等这类控制器特性。类Controller还使得使用方法newInstance()来创建控制器实例和经由方法forName()和forAlias()来获取控制器元数据描述成为可能。Method是描述控制器中动作(或方法)的类。Method提供方法来访问名称、返回类型和参数这类方法特性。Parameter是描述方法中参数的类。Parameter提供方法来访问名称和类型这类方法特性。ii.Deamons(守护程序)可使用以下3种方法来管理Composite值实例中字段的值:get(获取)、set(设置)和remove(去除)。上文所提及的每一方法的调用可影响其他字段的值或父Composite值实例的完整性。守护程序是在后台运行的监听器,且在每一基本方法(get、set或remove)之后进行调用,以便执行所要处理。守护程序分成以下4个部分:IfNeededDeamons:在对字段执行get操作后调用这些守护程序。每一字段具有一个IfNeedDeamon,其负责获取与字段的以下特性相关的值:calculated(已计算)、asp(应用程序服务供应商)、foreignpk(外pk)、foreigncode(外代码)、transient(暂态)、navigablerelation(可导航关系)、composition(组合)、association(关联)、pk、code(代码)等。举例来说,为Simple字段寄存IfSimpleFieldIsNeeded,且如果父值是新的,则返回字段缺省值,否则的话,则试图使用惰性过程来获取键的值。DefaultValueDeamons:当系统试图向字段分配缺省值时调用这些守护程序。每一字段具有一个缺省IfNeedDeamon,其负责获取与字段的以下特性相关的缺省值:pk、type(类型)、calculated(已计算)、hasadefaultformulataggedvalue(具有缺省公式标记值)、hasaninitialvalue(具有初始值)、sequence(序列)等。举例来说,针对stereotype为“sequence”的Simple字段寄存IfDefaultSequenceIsNeeded,且返回字段序列器的下一值。IfAddedDeamons:在设定字段的值之后调用这些守护程序。每一字段具有许多IfAddedDeamons,其负责维护字段值的完整性或完整Composit值实例的完整性。服务器启动时就计算IfAddedDeamons的列表。就字段的以下特性进行计算:calculationbase(计算基础)、codebase(代码基础)、pk、code(代码)、type(类型)、foreignpk(外pk)、foreigncode(外代码)、transient(暂态)、collectionrelation(集合关系)、indexfield(索引字段)、mandatory(强制)等。举例来说,如果我们更改代码字段的值,那么系统必须重新计算技术字段代码的值。这由守护程序IfCodeBaseIsAdded来执行。IfRemovedDeamons:在对字段执行去除操作之前调用这些守护程序。每一字段具有许多IfRemovedDeamons。这些监听器就字段的以下特性被寄存:calculationbase(计算基础)、foreignpk(外pk)、foreigncode(外代码)或immutable(不可变)(非可去除字段)等。举例来说,针对参与计算公式的字段寄存IfCalculationBaselsRemoved,并去除所计算字段的值。iii.DomainManagers(域管理器)域管理器是保持与字段相关的以下信息的类:possiblevalues(可能值)、visible(可见)、readonly(只读)、calculationbase(计算基础)、minmultipcity(最小多样性)和maxmultiplicity(最大多样性)等。添加域管理机制使得通过使用适配器设计模式在运行时定制字段的特性成为可能。如果开发人员需要可编程地定义所提到特性中的一个,那么应定义一个类,这个类扩展DomainManagerAdapter、逾越所要求方法并使用接口Initializer将这个类寄存为静态块中所需字段的域管理器。框架向服务器启动时计算的每一字段分配缺省DomainManager。iv.IntegrityChecker(完整性检查器)完整性检查器是负责验证字段值的完整性(正确性)的类。所有完整性检查器实施方法CheckerFieldIntegrify()的接口FieldIntegritychecker。每一字段可具有许多完整性检查器。所寄存的完整性检查器用来当接口Value中定义的方法checkIntegrity()被调用时验证字段内容的完整性。SimpleValue及其子类中提供的方法checkIntegrity()的实施例确保所包括值(值必须遵循minvalue(最小值)、maxvalue(最大值)、thepossiblevalues(可能值)等这类所定义约束)的有效性。CompositeValue中提供的方法checkIntegrity()确保以下每一字段的完整性:multiplicityranges(多样性范围)、valuechangeincaseoffrozenfield(冻结字段情况下的值修改)等。CollectionValue中提供的方法checkIntegrity()确保集合中所有所包括值的完整性。Palmyra框架提供另一数据检查机制:检查规则。可使用Rules(规则)机制来实施有关Composite值实例的业务规则。开发人员应定义实施接口Rule的类和定义方法verify()。当业务语法检查未被验证时,开发人员应丢弃类型RuleException的异常。l.包com.palmyra.arch.basicStruct.exception这个包含有框架定制异常。图33示出这个包提供的异常。主要异常如下:DataException(数据异常):这个异常是运行时间异常,其是数据操纵期间丢弃的异常的超类。IntegrityException(完整性异常):完整性被侵犯时丢弃。KeyNotFoundException(键未找到异常):非定义键被请求时丢弃。PalmyraIllegalFormatException(Palmyra非法格式异常):用户试图从未格式化字符串创建值时丢弃。RuleException(规则异常):业务规则未被验证时丢弃。ValueNotFoundException(值未找到异常):系统无法从与错误外pk或外码相关的存储获取实体时丢弃。ProcessException(过程异常):用来封装业务过程中丢弃的非Palmyra异常的运行异常。PalmyraClassNotFoundException(Palmyra类未找到异常):用户试图提取应用程序中未定义类的元数据定义时丢弃。ImmutableFieldException(不可被字段异常):用户试图去除不可变字段(pk、updateDate、updatorUserId)时丢弃。m.包com.pahnyra.arch.basicStruct.init这个包含有主类GeneralInitializer.java,其负责服务器启动时装载所有Palmyra类。这个类含有称作loadAllClasses()的方法,其负责以下:装载允许寄存所有Classe实例的存储器中的所有Palmyra实例。执行应用程序中的所有静态块。这些块可用来寄存每一组件驱动器的实施例。这个包含有含有接口:Initializer和PalmyraInitializer。接口Initializer可由非Palmyra类(业务类)实施,且接口PalmyraInitializer可由Palmyra类排他地实施。当开发人员需要在服务器启动时执行特定处理时,诸如,寄存动作处理器、装载特性文件或填入高速缓存,开发人员应实施所提到接口中的一个,并定义带有以下签名publicstaticbooleaninitialize的方法initialize。2.Expression(表达式)表达式定义应用程序业务的一些simple部分。表达式用于计算和缺省公式、业务规则、映射过程、生命周期设计等。表达式允许解析并评估用户定义的表达式(a=l,b>20,alias.f())。表达式可为算术表达式(a+1)、比较表达式(b<10)、逻辑表达式(c&d|e)等。在表达式管理的过程中,有两个子过程需要区分:Parsing(解析)和Evaluation(评估)。Parsing是表达式编译的过程,其生成评估表达式所用的结构。可使用以下两种方法中的一种来解析表达式:Expression.parse(Stringexp):执行语法检查。Expression.parse(Stringexp,Classecls):执行语法和语义检查。Evaluation过程目的在于获取表达式最终值。所生成结构的主要概念有Constant(常数)、Variable(变量)、Operation(运算)和Function(函数)。a.Constant(常数)Constant表示常数值。从头开始定义评估结果。Constant可具有不同类型(数字、日期、字符串等)常数的语法依据以下类型而变:Number(数字):1.2;45200L;5.32E8String(字符串):"constantvalue"Date(日期):'24/03/2006b'Boolean(布尔值):true;falseNullvalue(空值):nullb.Varible(变量)变量通常表示Value字段(例如,name、a、bl23、taxRate等)。变量是值由评估过程获取的字面。根据评估过程中使用的Value获取变量评估结果。变量用于定义Operation(运算)和Function(函数)。c.Operation(运算)运算时带有以下3项的表达式:Operand1(运算对象1)、operator(运算符)和Operand2(运算对象2)。Operand1和Operand2可以是变量或复杂表达式。以下是5组运算:Arithmetic(算术):+、-、*、/Logical(逻辑):!(not(非))、&(and(与))、|(or(或))Comparison(比较):>、>=、=、!==、<Assignment(分配):=Delimiter(定界符):;(用于生命周期中的动作)d.Function(函数)函数表达式可分解成2个部分:函数名称和参数。函数表达式的语法是alias.functionName(parameter1,parameter2...)(别名.函数名称(参数1,参数2…))。参数可以是变量或复杂表达式。可独立评估参数,然后用评估结果来调用函数。函数表达式的评估结果是函数调用结果。i.Service(服务)目标应用程序是可部署于分布式环境中的面向服务的系统。分布式平台由应用程序藉以部署的许多个经配置的应用程序服务器形成。服务是可在本地或远端调用的一组函数。服务还可以同步或异步模式调用。服务涉及使用独立于其实际物理位置的名称。Palmyra中的ServicePattern(服务模式)使用一个外观BIB来提供同步服务(称作Facade),以及一个消息驱动式beanEJB来提供异步服务(称作AsynchronousFacade)。因此,用户可得益于所有可用J2EE特征。SynchronousCall(同步调用):同步服务调用包括:构建待执行消息定义调用属性执行消息示例://准备待执行消息ServiceMessagemessage=BSFactory.getServiceDriver().createServiceMessage(X.class.getName(),"actionB");//将参数添加到消息message.setParameter("param0″,newStringValue(″firstparameter"));//在构建消息之后,其准备好被执行BSFactory.getServiceDriver().callService(message);对于每一控制器,Palmyra生成调用方类(ServiceNameCaller),其提供同步调用每一动作所需要步骤的实施例。示例:我们可调用我们在前一示例的一行代码中调用的服务。XCaller.actionB(newStringValue(″firstParameter"));AsynchronousCall(异步调用):为了异步调用服务,我们仅需要向方法callService()添加InvocationAttribute(调用属性)。这个InvocationAttribute使得我们能够确定调用类型,Synchronous(同步)或Asynchronous(异步)(缺省调用类型是Synchronous)。以下是一个示例:ServiceMessagemessage=BSFactory.getServiceDriver().createServiceMessage(X.class.getName(),″actionB″);//添加参数message.setParameter("param0",newStringValue("firstparameter"));InvocationAttributesatt=BSFactory.getServiceDriver().createInvocationAttributes();//该消息将被异步执行att.setAsynchronous(true);BSFactory.getServiceDriver().callService(message,att);使用UML类图来定义服务。这些服务由称作控制器的类来表示。控制器具有名称、较短名称或别名以及许多个方法。控制器被视为一组服务。然后所生成代码表示定义服务所需要的结构骨架,然后添加手动编写的代码以使得在不考虑技术方面的情况下覆盖方法的功能实施例。对于每一控制器,存在以下主要生成类:名称为X的接口:这个接口含有UML中指定作为控制器中动作的方法。称作AbstractX的抽象类:这个类用于技术原因,且不为这个控制器的用户所用。具体类XCaller:这个类含有接口X中定义的方法,且提供快捷键来借助服务的缺省合同调用服务X。具体类XFactory:这个类提供不同方法来得到服务X的已寄存实施例。开发人员必须提供扩展AbstractX的类,且他可以给这个类命名并编写额外代码来寄存它,否则他应将这个类命名为XImpl。可使用生命周期、表达式或手动编写的代码来调用UML模型中定义的服务。安全性模块来控制不同用户对服务的访问能力。可在运行时使用特定配置工具来配置服务的事务行为(不管服务是否支持事务,且不管服务是否启动新事务或嵌于调用方事务中)。PalmyraServiceModule(Palmyra服务模块)使得终端用户能够配置或运行以下服务:Istobecalledremotely(是否远程调用):远程服务配置。Istobeexecutedwithaspecifictransactiontype(是否用特定事务类型执行):服务事务配置。IstobebroadcastedeitherinaClusterortootherApplications(是否在集群(Cluster)或其他应用程序中广播):广播配置。对WebServices(Web服务)的调用完全由服务层来实施。运行时通过WebServiceConfiguration(Web服务配置)实例来完成调用web服务所需要的配置。ii.Lifecycle(生命周期)Lifecycle管理组件依据表示过程的相关联状态图,逐个监测对象转换。这个模块用来运行目标应用程序中定义的所有过程。有可能在运行时装载新过程并将其与先前定义的类相关联。系统在装载这些新过程之后立即考虑这些新过程。如上文所描述,状态图用来定义过程。可在形成状态图的状态的输入点定义动作。可定义条件以便引导执行路径。使用PalmyraExpressions语言(PEL)来定义动作和执行两者。还可定义过程,以便引导若干其他过程(一个过程用来控制并启动若干其他过程)。iii.Security(安全性)内部和外部认证和单点登录(sso)基于角色的授权iv.Job-Scheduler(作业安排器)PalmyraScheduler是Palmyra框架中负责管理已安排作业的执行的技术模块。作业是带有特定配置的PalmyraController方法。后者的配置是在运行时指定。作业可手动或自动创建、修改、删除、跟踪和执行。PalmyraScheduler管理包括重复和失败。PalmyraScheduler与PalmyraCalendar(日历)模块紧密相关,后者负责Holiday(假日)和BusinessCalendars(业务日历)管理。对于与PalmyraScheduler模块一起工作的PalmyraApplication(应用程序),设计时需要完成一些前提条件:需要在Controller中将待安排动作定义为方法。需要创建BusinessCalendar的实施方案。这个实施方案Entity应封装属性和Stereotype“code”。示例:我们将基于TestController的方法“add(添加)”以及称作“myCalendar(我的日历)”的实体MyCalendar的实例(都在图47A中示出)来配置Job(作业)。在运行时,JobEntry(作业条目)实例存储有关如何安排动作的所有必要信息。JobMessage(作业消息):待执行方法,例如,图47B中示出的serviceName“com.TestController”的actionName“add”。Repetition:安排从2009年12月24日起每日下午5点执行这个动作。重复还可安排为重复一次、每分钟重复、每小时重复、每周重复、每月重复或每年重复。图47C和图47D示出重复设定。HolidayTreatment:我们可以向日历myCalendar分配假日。举例来说,我们假定是2009年12月25日是年度假日,2009年12月26日是特殊假日,且周日是每周的假日。当如下执行作业时将考虑假日列表:是忽略还是考虑这个假日。假日创建在图47E、47F、47G和47H中示出。TrackExecution:PalmyraScheduler使得通过JobExecution实例跟踪Job的执行成为可能。如图47I和图47J所示,将在2009年12月24日下午5点第一次执行这个作业。JobExecution实例的状态设为Waiting(等待)。如果成功完成,那么状态将更改为Success(成功)。考虑到12月25日、12月26日和12月27日的假日,将在2008年12月28日下午5点第二次执行这个作业。图51示出Scheduler的UML。PalmyraScheduler的操作原则是每当创建新作业,将其添加到工作作业列表,并按执行的最近日期进行排序。命名为Palmyra-Scheduler-Thread的运行线程通过这个工作作业列表来知道将首先执行哪个作业,然后等待其执行时间并执行。创建Job导致创建对应JobExecution实例。执行作业在于基于作业的JobMessage信息创建合适消息,然后让Service模块处理。命名为Palmyra-Jobs-Feeder-Thread的线程是负责管理工作作业列表的线程。其每隔LOAD_JOBS_INTERVAL(缺省120分钟)刷新列表。刷新意味着向数据库发送查询,得到预期在后一时间间隔内执行的所有作业,例如,处于Waiting状态且执行日期“realDate”小于“(currentDate+LOAD_JOBS_INTERVAL)”的JobExecution实例。JobExecution实例的周期从状态“Waiting”开始(创建时),转到“Sent”(相关作业到达其执行日期且开始由Scheduler处理时),转到“InProcess”(jobMessage开始被执行时),且最终转到“Success”(如果jobMessage被成功执行)或“Fail”(如果出现错误,例如,发生Exception)。可在应用程序启动时通过称作AUTOMATCCALLY_START_SCHEDULER的特性或运行时通过ApplicationSchedulerMenu(应用程序安排器菜单)来开始Scheduler线程。PalmyraScheduler具有其自身的记录器,其具有非常特定的术语。图52是PalmyraSchedulerTrace(Palmyra安排器跟踪)示例的说明。C.StorageLayer(存储层)1.持久性持久性由以下若干主要子模块构成:EntityManager(实体管理器):负责接收和变换查询。DataStore(数据存储):负责与数据库通信并将结果返回给EntityManager。PQLParser(PalmyraQueryLanguage)(Palmyra查询语言解析器):EntityManager用来解析PQL查询。a.EntityManager(实体管理器)EntityManager是完全遵循Palmyra标准的控制器。EntityManager实施BusinessDelegate(业务委托)接口。从用户的角度来说,EntityManager执行与将Palmyra值保存到数据存储/从数据存储获取Palmyra值相关的全部工作。EntityManager用作接口和解析阶段。另外,EntityManager将处理委托给适合处理单元,而所述适合处理单元又执行实际工作。除了执行PQL语句的动作以外,EntityManager还定义了以下3组动作:(1)Formattingactions(格式化动作):这些动作用来格式化数据存储、更新其格式或更新其约束。这些动作仅迭代已配置的数据源,并调用适合数据存储中的对应规程。(2)Synchronization/deletionactions(同步/删除动作):这些动作用来插入、更新或删除数据存储中的值。(3)Searchactions(搜索动作):搜索满足相同条件的AbstractValue对象。以下段落说明负责执行以上各组动作中的每一个动作的组件。b.Context-DrivenApproach(上下文驱动式方法)以特定方式设计Persistence服务,以使得其在Persistence服务所执行的操作的状态与执行这些操作并操纵其状态的组件的逻辑之间提供方便的等级分隔。这个分隔通过定义含有这些操作状态的许多个上下文来实现。这些上下文是不含逻辑的bean状对象(例如,具有“set”和“get”方法的对象)。进行实际工作的组件是将上下文作为其参数并操纵这些上下文内容的单件无状态对象。这样一来,参数在操作处理的多个阶段之间的传递得到了简化,并且从性能角度考虑成本得到降低。Persistence服务执行操作的方式非常类似于产品沿着工厂中产品线移动而制成。产品进入产品线时还是一组原材料。然后进入逐个阶段。类似的,上下文可视为由多个单件组件进行处理的产品。初始状态时提供Persistence服务的原始输入,而其最终状态含有适合输出。因此,上下文可含有所有处理阶段所要求的许多属性。然而,每一阶段或每一组件仅与这些属性的子集相关。因此,每一组件必须具有其自身的上下文视图。在这种情况下,必须定义单件组件来获取子上下文作为参数。每一子上下文实际上是一个接口,这个接口定义应在上下文中呈现以供对应组件进行处理的属性子集。一个操作的上下文是执行这个操作所涉及的所有组件的所有子上下文的实施。c.处理单元如上文所述,EntityManager仅用传递到其的参数填入适合上下文,然后调用适合处理单元,从而传递将上下文传递过去。每一处理单元还可调用其他处理器单元等。所有处理单元实施具有取上下文作为其单个参数的单个方法(过程)的相同接口(Processor接口)。d.Cache-Aware(高速缓存感知)处理单元一些处理器可高速缓存其在执行运算时生成的一些或全部数据,因此,当稍后执行类似运算时,从高速缓存器获取待生成的数据,而不是重新生成。这类处理器称作高速缓存感知处理器,且它们扩展向高速缓存过程提供提取的类CacheAwareProoessor。举例来说,假定高速缓存感知处理器(称作P)处理含有输入属性a1、b1、c1和d1和输出属性a2、b2、c2和d2的上下文。当设计这个处理器时,开发人员(持久性层开发人员)必须选择可被高速缓存且每次都应处理的输出属性。从理论上来说,a1、b1、c1和d1的可能值的个数是无穷的。然而,假定在给定有限周期的应用程序使用寿命的实际情形下,我们发现,a1、b1和c1的可能值的个数非常有限,而d1的可能值的个数相对多。如果用户假定输出属性a2、b2、c2和d2直接分别对应于输入属性a1、b1、c1和d1,那么我们将推出如下结论:a2、b2和c2是可被高速缓存的,而d2应每次进行计算,因为a1、b1和c1(藉以生成a2、b2和c2)的重新出现频率高于d1的重新出现频率。此外,如果用户高速缓存d2,那么高速缓存器的大小应显著增大以放大性能。由于输入属性的可能值的个数通常不受限制,因此应使用循环高速缓存器,而不是使用映射来存储被高速缓存的值。循环高速缓存器保持最后和最常用的键。在我们的示例中,用于高速缓存的键应由输入参数a1、b1和c1构成。任何高速缓存感知处理器执行以下例程:(1)从上下文的属性生成高速缓存键。(2)使用所生成的高速缓存键来从高速缓存器获取数据。(3)如果找到了被高速缓存的数据,那么将被高速缓存的数据写入到上下文中,然后生成不可高速缓存的输出属性。(4)否则,生成所有输出属性、从上下文读取可高速缓存的输出属性,然后使用高速缓存键将读取到的可高速缓存数据放入缓存器中。在每一高速缓存感知处理器中存在这个例程,使得能够通过为执行高速缓存路由的所有高速缓存感知处理器定义超类来提取高速缓存过程,从而留存一些部分作为将在子类中逾越的abstract方法。类CacheAwareProoessor中存在一种用于以下每一任务的abstract方法:(1)从上下文生成高速缓存键。(2)生成所有输出属性。(3)生成不可高速缓存的输出属性。(4)从上下文读取可高速缓存的输出属性。(5)将被高速缓存的输出属性写入到上下文中。e.OperationExecuter(运算执行器)此后,由EntityManager首先调用的根处理单元称作运算执行器。这些运算执行器将遵循特殊的编号规则,以使得能加以辨别。如果运算的名称是Xxx,那么其执行器的名称将是XxxExecuter(例如,SelectExecuter、SynchronizeExecuter等)。除了调用其他处理器以外,运算执行器还用作其他处理器的工厂对象。如果处理器需要调用其他处理器,那么它可从运算执行器获得对那个处理器的引用。因此,运算执行器可视为处理器的中心“板”。这样一来,创建特定目的的定制执行器就变得简单可行。然而,这意味着运算执行器必须可访问其将调用的所有处理器,因此应在上下文中传递对运算执行器的引用。大多数Select(选择)执行器调用至少2个处理器。第一个处理器是映射处理器(或映射器),其生成将执行全部或部分运算的数据存储命令。第二个处理器是组译处理器(或组译器),其将读取数据存储返回的数据,并将结果组译到Palmyra值中。在调用映射器之后且在调用组译器之前,将映射器生成的命令经由数据存储包装所表示的特殊软件层发送到数据存储,所述数据存储包装是控制Persistence服务与数据存储之间的数据流的对象。一些运算要求执行一个以上数据存储命令。换句话说,为了执行一个运算,映射器和组译器可能会执行一次以上。因此,运算执行器应认出其执行的两种运算。第一种运算是可通过执行每一运算的单个数据存储命令来执行的原子运算。第二种运算是要求执行一个以上数据存储命令的组合运算。每一后一类运算可分解成较简单的原子运算,且运算执行器负责分解。f.PQL与SQL的比较EntityManager通过查询底层数据存储来执行PQL查询。数据存储提供的服务类似于关系数据库提供的服务。由于大多数关系数据库是通过SQL查询来查询,因此几乎每一数据存储运算可用SQL查询来表达。数据存储运算与SQL查询之间的一一对应使得SQL成为表达如何进行PQL查询的不错的工具。因此,将SQL用作伪查询语言,这很像用伪代码来说明如何实施特定算法。然而,详细细节(有关如何克服SQL的限制)不在本文的范围内。g.Search(搜索)动作Select执行器是所有select-operation(选择运算)执行器(诸如select-count(选择计数)、select-historicized(选择记录))和剩余类似执行器的超类。如上文所描述,像任何其他执行器一样,select执行器可多次调用映射阶段、数据存储和组译阶段,以便执行完整的选择或查找操作。这取决于以下两个因素:(1)所查询的键或搜索标准含有表示与接口的关系的键。(2)所查询的键含有表示一对一关系的键。h.处理接口考虑图37A和37B中的UML,假定查找操作中的所查询类是X,且所查询字段是+、i1.+、i1.i2.+和i3.+。由于接口没有数据存储容器且由于持久性服务无法提前知道与类型X的值相关的实体的实际类型,需要多次调用数据存储来查找这些实体。一种解决方案是在不获取键i1、i2和i3的情况下执行查询。然后惰性获取这些键。这种方法具有以下两个缺点。第一个缺点是用户无法向这些键添加约束,或用户必须在获取值之后评估这些条件并滤出不满足条件的值,这从性能角度考虑成本很高。第二个缺点是获取越多值,用户需要执行越多lazy-get(惰性获取)操作。举例来说,如果查询获取到类X的100个实例,那么针对每一实例,用户需要执行3个惰性获取操作来获取i1、i1.i2和i3。这意味着用户需要300次附加惰性获取操作来获取找到的所有实例的关系。换句话说,用户需要调用数据存储1+n*m次(其中n是获取到的值的个数,且m是带有接口的所查询关系的个数)。一种比较好的解决方案是将这类运算分解成许多个原子运算。在每一运算中,用户将每一所查询接口播送到一个实施所述接口的类中。通过使用这种方法,对于给定运算,对数据存储的调用次数将为常数。这个常数取决于实施每一所查询接口的类的个数。在我们的示例中,接口I1、I2和I3可如下播送:(1)I1作为Al、I2作为A2以及I3作为A3(2)I1作为Al、I2作为A2以及I3作为B3(3)I1作为A1、I2作为A2以及I3作为C3(4)I1作为A1、I2作为B2以及I3作为A3(5)I1作为A1、I2作为B2以及I3作为B3(6)I1作为A1、I2作为B2以及I3作为C3(7)I1作为B1、I2作为A2以及I3作为A3(8)I1作为B1、I2作为A2以及I3作为B3(9)I1作为B1、I2作为A2以及I3作为C3(10)I1作为B1、I2作为B2以及I3作为A3(11)I1作为B1、I2作为B2以及I3作为B3(12)I1作为B1、I2作为B2以及I3作为C3因此,如果用户具有引用这些接口的n个键,且如果c(i)是实施键数i所引用的接口的类的个数,那么原子运算的个数将为:考虑到我们的示例中存在第9次播送的可能性,也就是I1作为B1播送、I2作为A2播送以及I3作为C3播送的可能性,在这种情况下,图37A中示出的UML将简化成图37B中示出的第二UML。因此,Select执行器必须:(1)收集查询中涉及的所有键。(2)搜索引用接口的所收集键,并将其添加到列表。(3)计算所有组的类的Cartesian产品,其中所述所有组的类实施步骤(2)中找到的键所引用的接口。这将给出所有播送可能性。(4)对于每一播送可能性或组合,应执行原子选择运算。播送组合应放入运算的上下文中,因此稍后阶段知道如何播送每一键。所组译的值的个数一达到用户指定的待获取值的最大个数,Select执行器就必须中断播组合的迭代。上述情况的唯一异常是还指定次序的情况。在这种情况下,每一原子运算可获取值,直到达到指定最大值为止。然后,对所获取值进行排序和修整,以使得不超出所述值。这意味着涉及接口、次序和待获取值的最大个数的查询相当昂贵。i.从PQL到SQL的示例在前一UML样品(图37A和图37B)中,如果用户执行以下PQL语句:PQL:select+,i1.+fromXwherepk>1000Select执行器将执行以下SQL查询的等效语言:(1)在将i1播送到A1之后:selectT.*,T_il.*fromXTleftjoinA1T_ilonT.il$pk=T_il.pkwhereT_il.pk>1000(2)在将il播送到Bl之后:selectT.*,T_il.*fromXTleftjoinBlTilonT.il$pk=T_il.pkwhereT_il.pk>1000j.接口键收集器如上文所描述,Select执行器需要知道接口所引用查询中存在的键,且因此,Select执行器必须在查询中迭代所有呈现的键,以便搜索接口所引用的键。然而,这类键可在所查询键、搜索标准、分组功能和其他字段中找到。换句话说,这些分别在许多个结构中。接口键收集器遍历Select执行器上下文中的所有结果,且收集接口所设计的键。结果是将每一所述键映射到其引用的键的映射。Select执行器使用这个映射来生成所有播送组合。k.处理1对N关系以下段落中将国家与城市之间的关系作为示例。这是1对N关系,因为每个国家含有一个或更多个城市。在数据存储中,城市容器中的记录必须含有引用国家容器中的记录的外键。如果关系的名称是“cities(城市)”,且对称关系的名称是“country(国家)”,那么外键的名称是“countrySpk”。考虑以下PQL语句:select+,cities.+fromCountrywherearea>1000PQL语句的明显SQL等效语句将是:selectT.*,T_cities.*fromCountryTleftjoinCityT_citiesonT.pk=T_cities.country$pkwhereT.area>1000由于前一SQL语句的结果不具有树状结构(实际上是含国家和城市的字段的一组记录),一个国家的属性可在属于这个国家的许多城市的记录中找到。这些记录的唯一不同就是城市的属性。这个冗余将耗费大量存储器和网络带宽。另外,需要附加计算来将这个大组简化成树。借助这类PQL,可用单个SQL语句进行查询。参照图41C,我们需要执行查找操作来提取X实例及其Y实例,那么Persistence层将生成如下形状的查询:selectT_.accessPoint_,T_y_.x$code_,T_y_.x$pk_,T_y_.accessPoint_,T_y_.creationDate_,T_y_.creatorUserId_,T_y_.pk_,T_y_.type_,T_y_.updateDate_,T_y_.updatorUserId_,T_.creationDate_,T_.creatorUserId_,T_.pk_,T_.type_,T_.updateDate_,T_.updatorUserId_fromtest_X_T_leftjointest_Y_T_y_on(T_.pk_=T_y_.x$pk_)orderbyT_.pk_asc一旦数据存储层返回封装结果的记录实例的向量,组译器就扫描这个向量两次,一次是创建X实例,而另一次是创建Y实例,并在所创建的实例之间进行组合。l.进一步优化考虑到图38中的以下UML,举例来说,假定我们想要执行以下查找操作:select+,i1.+,i1.i2.+fromXwherepk>1000如果我们遵循前一方法,那么通过如下播送i1和i2来将查询分成4个较小的查询:(1)I1作为A1、I2作为A2(2)I1作为A1、I2作为B2(3)I1作为B1、I2作为A2(4)I1作为B1、I2作为B2然后,因为i1与i2之间的1对N关系,4个小型查询中的每一个将再次分成2个原子查询。我们以前面2个组合作为示例:(1)在将I1作为Al且I2作为A2播送之后,Select执行器将执行以下2个查询:PQL1:select+,i1.+fromXwherepk>1000casti1toA1andi2toA2PQL2(1对N):select+,i1.i2.+fromXwherepk>1000casti1toA1andi2toA2(2)在将I1作为Al且I2作为B2播送之后,Select执行器将执行以下2个查询:PQL3:select+,i1.+fromXwherepk>1000casti1toA1andi2toB2PQL4(1对N):select+,i1.i2.+fromXwherepk>1000casti1toA1andi2toB2注意,查询PQL1和PQL3中播送子句中的第二项并不重要,且可以忽略,因为i2在查询中并不持久。另外,这个播送将不会影响所生成的SQL查询。因此,如果我们忽略,那么PQL1和PQL3将相同且获取相同值。因此,如果我们检测到这类查询,可进行进一步优化。m.简化组合前一问题的解决方案是在生成每一原子查询之前检测非必要播送项,并忽略,从而生成新的简化组合。如果Select执行器保持所执行原子查询的一组简化组合,那么在简化组合已存在于所述组的情况下能跳过原子查询。在一个示例中,在生成PQL1之前,组合(A1,A2)将简化成(A1)。这个简化组合将在执行PQL1之后添加到简化组合组中。在生成PQL3之前,组合(A1,B2)将简化成(A1),而其已存在于简化组合组中。在这种情况下,可跳过查询PQL3。检测非必要播送项的过程很简单。将可看出,生成原子查询的第一步是收集所述查询中存在的所有键。因此,如果播送项的键并不存在于所收集的键中,那么可放心地忽略所述播送项。n.映射阶段映射阶段负责从上下文内容生成数据存储命令。如果通过执行多个数据存储命令来执行运算,那么运算执行器必须针对每一命令修改上下文的内容并调用适合映射器。另外,映射阶段可生成用来优化随后组译阶段的工作的数据。映射阶段未必由处理器对象来表示。映射阶段是可由多个处理器表示的逻辑阶段。对于给定的输入来说,最终数据的部分始终是由映射器生成。这些部分可被高速缓存,因此映射器无需在每次接收到相同输入时都重新生成。可以这么做,只要我们假定这些数据依赖于指定操作的当前用户。出于安全性考虑,实体管理器可能需要依据正执行操作的当前用户来修改这个操作的输入(例如,添加安全性条件)。这意味着相同PQL查询可能会针对每一用户形成不同的数据存储。因此,大多数阶段应分成以下2个阶段:适应阶段和变换阶段。适应阶段依据用户特性修改输入,以使得这个输入变成独立于用户。变换阶段将独立于用户的输入变换成数据存储命令。适应阶段由称作适配器的处理器来表示。而变换阶段由称作变换器的另一处理器来表示。由于与变换相关的数据需要适应并独立于用户,因此变换器可以是高速缓存感知处理器。o.选择适配器如上文所描述,选择适配器修改输入,以使其独立于当前用户。选择适配器主要调用称作CriterionExpander(标准扩展器)的处理器,其通过以下标准扩展输入标准对象:(1)安全性标准:针对根查询类和与根查询类具有直接或间接聚合关系的每一查询类,标准扩展器添加安全性标准。(2)隔离标准:这些标准建自根查询类中ASP字段的值。这些值从当前用户特性获取。p.标准扩展器由于隔离标准的实施很简单,本文档将不进一步讨论。然而,添加安全性标准实施起来并不容易。不同于隔离标准,针对根查询类和与根查询类具有直接或间接聚合关系的所有查询类,添加安全性标准。当我们调用安全性模块来查询一个类的安全性标准时,所返回标准中的键与所述类相关,而并不与查找操作中的根查询类相关。这意味着不能像原来那样添加安全性标准。必须转译这些键,以使得其变得与根查询类相关。考虑图39中的UML。举例来说,假定查询键如下:[+,a.b.c.y.+]在这种情况下,应针对类X和类Y(A、B和C与X具有组合关系)添加安全性标准。假定针对Y的安全性标准如下:sc.sb.sa1.d.id==1000我们不能像原来那样添加标准,因为其并不是由X的键来表示,且因此应进行转译。转译的最简单方法是如下向标准的键添加前缀:a.b.c.y.sc.sb.sa1.d.id=1000这种方法的缺点是它可能会要求数据存储阶层的大量联合运算,因为组合键中的每一“点(dot)”表示联合运算。在前一示例中,组合键“a.b.c.y.sc.sb.sa1.d.id”可简化成以下键“a.d.id”。但这仅在关系为1对1关系时可用。表25示出生成简化组合键的算法。表25:生成简化组合键的算法q.键扩展器由于标准扩展需要知道所有查询键才能构建安全性标准,必须在扩展标准之前扩展键,从而意味着查询键不得含有两个使用的“通配符(wildcard)”(例如,和“+”)。相反,这些字符必须用其所表示的键来替换,而这正是键扩展器的预期目的。另外,对于稍后的变换阶段来说,也有必要进行键扩展。然而,由于在1对1键之后查询1对N键,这两类键必须分隔开。因此,键扩展器并不生成Keys结构。相反,键扩展器生成含有许多个分隔开的Keys结构的特殊结构。在不同原子查询中查询这些Keys结构中的每一个。图40的UML类中示出这个结构。称作“第一”关系的键是将在下一原子查询中获取的键,而“第二”关系是指将在稍后原子查询中获取的一组键。这些查询获取到的值具有1对N关系,且值是从“第一”获取键组译得到。针对1对N关系的键是“第二”关系的映射的键。实际上,这个结构与其所封装的Ckeys结构具有相同树状结构,但它旨在在表示1对N关系的键处分隔Ckeys结构。处理Select执行器中1对N关系的方法实际上递归地遍历所扩展的Keys结构且在每一递归阶层执行必要的原子查询。尽管扩展键是SelectAdapter(选择适配器)执行的较早过程,但由于其仅取决于元数据,而并不取决于用户数据,因此选择适配器可以是高速缓存感知处理器。r.键收集器稍后可看出,数据存储需要知道查询所涉及的所有表,以及如何联合这些表。为了指定这些表,必须收集查询中存在的所有键。键收集器执行这个任务。键收集器遍历选定上下文中存在的许多个结构(例如,查询键、分组功能、次序键和标准)且收集这些结构中的键。这个处理器的输出是含有所有所收集键的单个Keys结构。键收集器不属于适应阶段,也不属于变换阶段,因为它不生成任何数据存储结构。然而,由于键收集必须遵循适应过程,键收集器可以是高速缓存感知处理器。s.组译器这个处理器负责依据DataStoreService(数据存储服务)所提供的记录列表创建Value对象。组译器迭代Record实例的这个列表,并依据KeyExpander所扩展的所要键创建Value。在要求待提取关系的Find(查找)操作的情况下,组译器多次扫描这个列表,以便创建这些关系的实例。组译值可以是取决于值的大小(待设字段的个数)的昂贵步骤。为了优化这个关键步骤,Palmyra框架使用多线程方面来使得组译步骤并行。并不是所有查找操作都能使用多线程组译器,因此,组译器依据所组译的键来决定是否并行工作。t.收集标准的1对N键考虑以下PQL语句:select+fromCountrywherecity.population>1000000由于关系“city(城市)”是1对N关系,且前一查询返回的每一国家具有满足搜索标准的至少一个城市。等效SQL语句将是:selectT.*fromCountryTjoinCityT_cityonT.pk=T_city.country$pkwhereT_city.population>1000000当我们从城市关系查询字段时产生问题。举例来说,考虑以下PQL语句:select+,city.+fromCountrywherecity.population>1000000由两个SQL语句来执行这个查询。第一个SQL语句与先前所示的SQL语句相同。如果我们遵循选择执行器所执行的相同步骤,那么查询将是:selectT.pk,T_city.*fromCountryTjoinCityT_cityonT.pk=T_city.country$pkwhereT_city.population>1000000然而,对于每一获取到的国家,这个查询将仅获取人口超出1000000的城市。稍后同步这些国家将导致人口未超出1000000的城市被删除,而这不是我们的预期行为。解决方案是改为执行以下SQL语句:selectdistinctT.pk,T_city.*fromCountryTjoinCityT_cityonT.pk=T_city.country$pkjoinCityC_cityonT.pk=C_city.country$pkwhereC_city.population>1000000在这个查询中,我们将表City与表Country联合两次,从而针对表City给出2个不同别名。从第一别名获取表City的字段,而依据第二别名指定条件。关键词“distinct”用来避免获取每一城市的多个复制。由于标准的1对N键被给出不同别名,必须用键控制器来标记,以使得变换器生成适合的表联合。u.SelectTransformer(选择变换器)每次SelectExecuter想要生成数据存储查询时,SelectExecuter调用选择变换器(SelectTransformer)。因此,SelectTransformer将原子查询(其属性可从上下文获得)变换成数据存储查询。SelectTransformer的实施含有对其他处理器或变换器的一连串调用。这些处理器将上下文中的结构如下变换成其数据存储的对应部分:Queried/NeededKeys(查询/需要的键)->DataStoreMetaRecord(数据存储元记录)(所查询字段)QueriedClass(查询的类)+CollectedKeys(收集的键)->DataStoreTableStructure(数据存储表结构)CriterionDataStoreCondition(标准数据存储条件)GroupFunctions(组函数)->DataStoreFunctions(数据存储函数)(求和、最大值、最小值等)GroupFields(组字段)(次序字段)-DataStoreOrderRecord(数据存储次序记录)OrderFields(次序字段)->DataStoreOrderRecord(数据存储次序记录)SelectTransformer执行相对繁重的操作,且因此其必须是高速缓存感知处理器。v.KeyTransformer(键变换器)无论存在于所查询键中还是搜索标准中还是任何其他结构中,原子查询中的每一键应变换成数据存储字段。数据存储字段是前缀表示字段所存在的表别名且后缀是字段名称的组合键。由于所有变换器都需要进行键的这类变换,应由所有变换器共用的另一对象来进行这个通用操作。这个对象是KeyTransformer。一些键可能会在原子查询中出现多次且呈不同结构。因此,可调用键变换器来多次变换相同键。为了降低这类重复变换的成本,键变换器必须维护所变换键的内部映射。这意味着键变换器是无法在不同操作中重复使用的完整状态对象。然而,如果再次执行相同查询,那么可高速缓存键变换器以供稍后使用。因此,可将键变换器传递到上下文中的变换器中。变换器必须遵循以下规则:(1)Relations(关系):是composite还是simple,仅生成表别名。(2)Keys(键):是composite还是simple,表示simple属性,生成完整的数据存储字段(例如,别名+字段名称)。(3)相同关系或键生成相同别名和数据存储字段。(4)两种不同的关系永远无法生成相同别名。(5)两种不同的键永远无法生成相同数据存储字段,但假定它们前缀相同且后缀表示在相同类中宣称的simple属性,它们可能会生成相同别名。(6)在标准中标记为1对N键的键是不同组的键。变换这类键不应生成由其他键生成的相同别名。然而,这组中的变换仅遵循先前的规则。KeyTransformer将所扩展的查询键变换成查询数据存储字段的元记录。变换很简单,因为它仅迭代叶键并调用每一键的键变换器。举例来说,考虑图41A和图41B中的UML图,同时还考虑以下PQL语句:select+,y.+,y.z.+fromXwherepk>1000通过执行一个SQL查询来执行上述查询:XView是X和Y的视图,而ZView是Z的视图。在这个情境下,由于将不组译类Y的实例,无需获取Y的主键。相反,应获取X(或XView)的主键,且第二查询将如下进行:selectdistinctT.pk,T_y_z.*fromXTleftJoinYT_yonT.y$pk=T_y.pkjoinZT_y_zonT_y.pk=T_y_z.symY$pkwhereT.pk>1000进行这个更改是因为,在执行第二查询之前,所组译值的高速缓存将仅含有类XView的实例,且针对这些实例的键将是X的主键。实际上,SelectExecuter负责确定待添加的隐式键,因为SelectExecuter是递归得迭代待获取1对N键的处理器,且因此SelectExecuter是知道前一递归阶层的主键的唯一处理器。w.TableBuilder(表构建器)TableBuilder构建表结构,其指定表如何联合且别名如何提供给这些表。为了构建这个结构,TableBuilder递归地遍历所有所收集键,因为所收集键含有查询中存在的所有键。TableBuilder使用KeyTransformer来确定表的别名。如下联合表:(1)Relationjoins(关系联合):将每一关系变换成两个相关类的两个表之间的联合。(2)Generalizationjoins(泛化联合):将超类的表联合到其子类的表。(3)从表示关系的字段的元数据获取关系联合的条件。(4)泛化联合的条件是T1.pk=T2.pk,其中T1是超类的表的别名,且T2是子类的表的别名。(5)非强制关系的联合是左联合。强制关系或泛化的联合是内联合。2.Palmyra中的历史服务Palmyra框架使得每当类型实例更改时保存其图象成为可能。为了实现这一目标,类型必须实施类型Historicized的接口。参照图46。对于每一类型Historicized,Persistence层创建另一表及其原始表,以便保存所述类型实例的图象。表名称添加由后缀项History_。注意,这个表含有列pk_,但不是唯一列,因为相同实例的图象具有实例本身的pk。向这个表的列(pk_、creationDate_)添加唯一约束,且表History的列于原始表的列相同。每次创建、修改或删除实例时,图象保存在表History中。可使用类型HistoricizedOnDelete的接口来完成异常,其使得系统仅可在删除操作中保存图象。通过按同步事件的精确时间填入creationDate列和按值Long.max填入updateDate列来保存图象。当需要保存另一图象时,上一图象的updateDate值将取当前同步日期,就像新图象的creationDate列等。Pk名称年龄创建日期更新日期10Alain2008/08/200809/08/200810Alain2509/08/200810/08/200810Alain3010/08/200811/08/200810Alain3511/08/2008Long.Max示例:如果要求得到pk=10且日期介于2009年8月8日到2009年8月11日之间的Person(人)实例的图象,其中,那么系统将执行如下查询:3.带有大量结果的查找操作对于执行可能返回大量结果的查找操作来说,Palmyra框架足够安全。获取大容量可能引起存储器问题。所用技术是将查找操作中所要求实例的pk带入使用已传递标准的所关注表的pk列,然后,当迭代结果的一些日期时,系统使用所获得的pk子列表来提取结果页面。使用类LazyPageByPageCcllection来完成页面查找操作。这个类使得按序随机访问结果成为可能。使用以下方法来通过获得特殊迭代器来完成按序访问:通过设定待获取页码来完成随机访问,然后使用以下方法来访问:以及a.SynchronizeActions(同步动作)为了同步值,实体管理器依据动作类型(删除、插入或更新)调用合适“ProcessExecuter”。Palmyra中操纵的所有值都具有类型DeepMap。因此,出于这个原因,ProcessExecuter检查完整性和权限,并调用遍历所有对象关系且调用合适Mapper(映射器)的Traverser(遍历器)。b.ProcessExecuter(过程执行器)图42的UML中给出ProcessExecuter的设计模型。所有同步动作的超类是类“ProcessExecuter”。删除动作的处理不同于另外2个动作(插入和更新)。出于这个原因,我们具有2个子类“SynchronizeExecuter(同步执行器)”和“DeleteExecuter(删除执行器)”。c.Traverser(遍历器)图43的UML图中给出Traverser的设计模型。存在以下两类遍历器:(1)SingleTraverser(单遍历器):遍历单个值且对这个值执行动作。单个Traverser具有2个子类“DeleteTraverser(删除遍历器)”和“InsertTraverser(插入遍历器)”。(2)UpdateTraverser(更新遍历器):遍历2个值,其中旧值从数据库获得,而新值由用户修改。d.Mapper(映射器)图44的UML图中给出Mapper的设计模型。数据库中最后执行的动作时删除、插入或更新动作。出于这个原因,我们具有以下3个类:类DeleteAction(删除动作)、类UpdateAction(更新动作)和类InsertAction(插入动作)。所有同步动作的超类是类SynchronizationAction(同步动作)。4.PersistenceLayerListener(持久性层监听器)持久性层使得干扰查找、组译、保存和删除操作成为可能。搜索监听器:为了操作针对搜索操作的监听器,程序员必须实施接口SearchListener(搜索监听器)并将实现器寄存到关注搜索类型的Classe中。在开始所需查找操作之前调用这个监听器。这个监听器通常用来更改已传递标准。组译监听器:就像前一类监听器,程序员必须实施接口AssembleListener(组译监听器)并寄存这个实现器:对于同步操作来说,在以下一个或更多个情形下程序员必须实施接口SynchronizeListener(同步监听器),并寄存待调用的实现器:插入之前。插入成功之后。插入失败之后。更新之前。更新成功之后。更新失败之后。注意,寄存使用经由BSFactory.getPersistenceDriver()获得的持久性驱动器;注意:由于运行时完成寄存,那么程序员必须使用条件性子句对监听器必须起作用时的情形进行控制。对监听器的调用是累计的,这意味着除了所关注类型的监听器以外,Persistence层还调用针对所关注类型实施的接口寄存的所有监听器。使用监听器适配器来收集这些监听器,所述监听器适配器对针对所关注类型必须被调用的所有监听器进行分组。监听器适配器被高速缓存,以使得每次要求监听器适配器时Persistence层无需进行重新计算。a.数据库连接服务持久性层基于经由JDBC与数据库直接通信的数据连接服务。为了优化性能数据库,供应商通常提供更好地支持其产品的特定驱动器。将数据库连接服务与实体管理器分开,使得能够针对每一供应商使用正确的驱动器而无需在持久性层中进行任何修改。本领域技术人员从上述规范将易于了解优选实施例的上述和其他优势。因此,本领域技术人员应理解,可在不偏离本发明的广泛发明概念的情况下对上述实施例进行更改或修改。因此,应了解,本发明并不限于本文描述的特定实施例,而是预期包括所附权利要求书的范围和精神内的全部更改和修改。这个层负责处理针对时刻Oracle、MySql、MSSqlServer以及DB2的不同RDBMS。类似于Persistence层的数据存储层使用上下文模式。另外,这个层广泛地使用多态,以便针对每一KDBMS建立方言。数据存储层使用标准SQL规范处理DBMS,但在一些情况下,可能会由于标准SQL与供应商特定SQL之间的不同而产生一些偏差。管理与RDBMS的通信的缺省类是Dbds,且处于对上文提到的偏差的考虑,Palmyra框架形成这个主类的子类。参照图45。使用规程在数据存储成中完成对KDBMS的处理,且规程可独自进行整个操作,或者也可调用一些其他规程来完成作业。类Dbds提供对不同规程的访问,所述不同规程负责执行从Persistence层变换的操作。当Dbds的子类为了提供适合RDBMS而逾越某个proceduregetter时,多态清晰地出现。所有数据存储规程实施接口Procedure:示例:在MySql中,为了获得行号,SQL语句应使用表达式@rn,而不是Oracle中所使用的rownum,这意味着负责insert-from-select语句的规程必须特定于供应商,因此,在Dbds中返回这类规程的方法在相关RDBMSDbds类中有所逾越。在Dbds中:在MySqlDbds中:此外,本技术还可以如下配置。(1)一种用于使用计算机系统来生成软件应用程序的方法,其包括以下步骤:(a)在所述计算机系统中实施的图形设计工具410中对业务过程建模;(b)通过使用表示所建模的业务过程的一个或更多个状态图以及表示数据模型并表示应用到所建模的业务过程的预定的业务规则的一个或更多个类图,在所述计算机系统中创建至少一个UML模型,以形式化在步骤(a)中建模的所述业务过程;(c)通过使用预定的语法来检测语法错误,在所述计算机系统中验证所述至少一个UML模型420,以验证所述一个或更多个状态图或所述一个或更多个类图或者所述一个或更多个状态图和所述一个或更多个类图的组合;以及(d)在所述计算机系统中将在步骤(c)中验证的所述至少一个UML模型变换成用来生成所述软件应用程序的功能性和非功能性方面的元数据。(2)根据(1)所述的方法,其中所述变换步骤包括生成所述软件应用程序430。(3)根据(2)所述的方法,其中所生成的所述软件应用程序与先前存在的库440相组合。(4)根据(2)所述的方法,其中所生成的所述软件应用程序与手动编写的代码450相组合。(5)根据(1)所述的方法,其中所述元数据包括应用程序代码、约束模型、自动化文件和文档中的至少一个。(6)根据(2)所述的方法,其中所生成的所述应用程序包括预定的功能性要求集合。(7)根据(2)所述的方法,其中所生成的所述应用程序包括预定的非功能性要求集合。(8)根据(7)所述的方法,其中所述预定的非功能性要求集合包括安全性管理、装载平衡、事务管理、用户接口和在其上构建算法的骨架至少之一。(9)根据(2)所述的方法,其中所述生成步骤包括向所生成的所述应用程序添加手动编写的代码。(10)根据(1)所述的方法,还包括借助部署工具490部署所述目标应用程序。(11)根据(1)所述的系统,其中所述语法包括用于类(composite、constrainable、entity、macro、viewable)、状态(loadable)、字段(ASP、code、sameas、sequence、transient、unique)和关系(code、list、map、set、transient、unique)的Stereotype()。(12)一种用于使用计算机系统来生成软件应用程序的方法,其包括以下步骤:(a)在所述计算机系统中实施的图形设计工具410中对业务过程建模;(b)通过使用表示所建模的业务过程的状态图以及表示数据模型并表示应用到所建模的业务过程的预定的业务规则的类图,在所述计算机系统中创建至少一个UML模型,以形式化在步骤(a)中建模的所述业务过程;(c)通过使用预定的语法来检测语法错误,在所述计算机系统中验证所述至少一个UML模型420,以验证所述状态图或者所述类图或所述状态图和所述类图的组合;以及(d)生成所述软件应用程序430,使得通过将经验证的所述UML模型变换成源代码、将经变换的代码与先前存在的库和配置文件相组合,能够将所述软件应用程序部署到服务器。(13)根据(12)所述的方法,其中步骤(d)包括将经验证的UML模型变换成用来生成所述软件应用程序的功能性和非功能性方面的元数据。本领域技术人员从上述规范将易于了解优选实施例的这些和其他优势。因此,本领域技术人员应理解,可在不偏离本发明的广泛发明概念的情况下对上述实施方案进行更改或修改。因此,应了解,本发明并不限于本文描述的特定实施方案,而是旨在包括所附权利要求书的范围和精神内的全部更改和修改。当前第1页1 2 3 当前第1页1 2 3 
当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1