1、,Agenda,Windchill开发内容集合开发目录介绍 开发环境搭建 Windchill 模型环境搭建 Windchill类的介绍 Windchill各个业务对象的模型介绍 Windchill常用开发类和方法介绍,开发规范,JAVA开发规范,请遵守sun标准 Windchill开发规范 由于将来系统生产环境是Cluster架构,所以在编写代码时,要尽量避免使用Static的Class变量,测试环境配置多个Method Server,以防止编写的代码在Cluster环境中运行出现问题。 系统运行的错误信息,要显示在UI界面上,以便用户和系统管理员了解,同时需要在系统log中记录。 Debug
2、语句要有开关控制,避免直接使用System.out.println()打印,导致将来的生产环境产生大量日志。 每个客制点之间,设定一个Debug开关,方便自身模块的调试。Debug的开关,缺省值设置为false。客制点之间的输入和输出部分,需要输出Debug信息,方便客制点之间的调试。 工作流中的表达式,具体实现,都写在WfUtil中,只在工作流中调用WfUtil中的方法。WfUtil中的方法注释中,需要说明该段代码,将在那些workflow中被调用。 系统OOTB配置部分通过XML配置文件交付。方便新系统可以直接通过LoadFileSet导入配置。 系统内部值,例如IBA,全部由英文字母和数
3、字组成,不能包含特殊字符。 禁止反编译系统OOTB的Class文件,然后在此基础上修改做客制,导致系统无法升级。 需要对出厂文件(HTML template等)修改时,需要保存原出厂文件的备份在wtSafeAreaptcOrig目录下,修改后的文件另存到wtSafeAreasiteMod目录 需要增加的properties属性不要放置在wt.properties中(service的注册除外),其他都放置在codebasecomitbgext.properties。 客制的新增Class文件放置在codebasecomitbg对应的目录下。不要放在系统原有的包中。(除非使用了系统原有的Prote
4、cted Method,这种用法要尽量避免).,设计规范,设计规范之建模 仅对持久化对象建模只有数据需要保存到数据库中的持久化业务对象才允许进行建模。其余的操作类(例如:Processor、Delegate、Helper类等)不被允许进行建模。 模型命名规则对象的名称、属性名称、方法名称应该满足命名规则,同Java编码规范的类命名、变量命名和方法命名。例如:类名 TRApplyDoc属性名trPhase方法名getFormData说明:历史的模型如果要更改将要做数据迁移。因此只要求对新建立的模型,历史模型不做要求。,设计规范,字段扩展对于对象的属性,一般情况下采用默认长度。建模时要求考虑属性长
5、度是否符合要求,如果需要加大长度,在模型中设置相应的值即可。 选择父类对于建模,尽量继承底层的Windchill类,例如:ManagedItem等,继承上层的具有实际业务含义的Windchill类(例如:WTPart、WTDocument)时,在业务上符合“是一个(As -is)”的含义,例如:EleadPart是一个WTPart 不预留属性对象建模,不预留属性。对于已有对象的预留属性,因属性名称业务含义,也不允许使用。历史模型已预留的属性不做要求。例如:不再使用以前建模留下的reserv1、reserv2等预留属性,设计规范,关联关系两个对象关联时,需要使用模型的关联关系。尽量不要采用建模为
6、两个独立对象,在一个对象的属性中记录另一个对象的某个标志属性的方式。例如:错误的建模方法:CBBCounter类有一个属性cbbNumber,记录CBB的编码。正确的建模方法:引入一个Link对象,记录CBBCounter类和WTPartMaster类的关系。 布局类图中尽量保证各部分分布均匀,连线尽量不要交叉,整个类图能够显示在一个屏幕范围之内(标准1024*768分辨率),对于引用的其他包的类、接口,可以将其属性、方法隐藏起来。避免占用过大的显示空间。,建模搭建环境,进入到Windchill+Information+Modeler-091_F000lRational_Rose_for_Wi
7、ndowssetup.exe安装 安装完成之后,load注册文件 进入到WT_HOMEroseAddIn,将VirtualPathMap.AddIn.reg和Windchill.AddIn.reg文件中的路径修订为个人本机环境的路径并注册,建模搭建环境,启动rose,点击“Edit Path Map”查看注册信息,Rose模型介绍,打开Rose模型,点击FileOpen选择srcwtWTdesigner.mdl,Rose模型使用,点击【是】,系统会加载其中Logical View是系统核心逻辑显示,其中3rd是Windchilll中使用了哪些Java技术模块、ext是系统客制化扩展模型目录、w
8、nc是Windchill核心业务逻辑组成 点击Save AS,重新命名为HelloWorld.mdl文件,弹出框选择No,环境搭建好后,即可创建模型,扩展模型,模型扩展(续),针对上面的图示,自定义个模型EleadDocs,继承WTDocument,该模型自定义方法getEleadDocName()和属性eleadDocType,且将其属性设置constrain=false,点击保存(遇到提示,点击No) 选择菜单Units.Control docs,保存为docs.cat,模型扩展(续),生成系统文件,选中docs包,模型扩展(续),生成系统文件.mData和EleadDocs.java文件
9、在src目录下自动生成包路径和文件 docs.mData和EleadDocs.java,模型扩展(续),系统会自动生成SQL【WT_HOME】dbsql3exteleaddocs 生成.ser文件【WT_HOME】codebaseexteleaddocs 执行SQL语句 进入到 Oracle SQL*Plus路径,执行命令:操作完成之后,即可使用EleadDocs对象了!,模型扩展(续),模型扩展(续),完整的例子说明 在windchill/src/目录下建立一个helloWorld目录,在windchill/codebase/目录下也建立一个helloWorld目录 打开rose软件,依次打
10、开fileopen定位到windchill/src/wt/WTdesigner.mdl,打开出现这个对话框,选择是,然后就耐心等待系统加载完这个文件。当完全加载完以后把这个文件保存到上面建立的windchill/src/helloWorld目录下,名称为helloWorld,模型扩展(续),打开helloWorld. Mdl,打开后如下图你可以发现你打开的时候是没有wt,java,helloWorld这3个package的,因为这3个package中wt和java是从左边的方框中拖过来的,而helloWorld这个是我自己建立的,然后把helloWorld和wt,java这2个package建
11、立关系如上图。然后双击helloWorld这个package在这个package中开始创建类。,模型扩展(续),打开helloWorld这个package后会出现下图,模型扩展(续),你打开的时候是什么都没有的,这里面person,personLink这2个类是自己建立的,可以从中间的那个条中选择到的,然后对这2个类进行编辑,选中person这个类,点右键,会出现点击第一个,然后就会出现,模型扩展(续),模型扩展(续),选择attributes这个标签,模型扩展(续),然后在空白的地方点右键就会出现一个快捷菜单,在这个菜单中可以创建一个变量,然后双击变量会出现,模型扩展(续),在这个里面会对这
12、个变量的类型进行设置,然后点windchill标签找到constrain这项,设置value为false,每个变量都需要这样进行设置,然后让这个类继承wt.fc.Item这个抽象类,这样就表明person这个类现在是持久的。同理把person这个类和wtpart这个类建立关联,关联的类为PersonLink然后让personLink继承ObjectToObjectLink这个类,然后把这个helloWorld. mdl保存一下,然后依次打开fileunitscontrol,然后再依次打开,toolswindchillsystem generation,模型扩展(续),选中前3项点OK,然后这个
13、时候你就可以在windchill/src/helloWorld这个目录下看到有Person.java和PersonLink.java这2个java文件,并且在windchill/db/sql3/helloWorld这个目录下面也会产生几个sql文件,把这几个sql文件导入到数据库中建立相关的表,要注意建立的先后顺序:只用操作以create开头的3个sql文件,模型扩展(续),修改Person.java加入下面的代码 protected void initialize() throws WTExceptionDate today = new Date();super.initialize();S
14、ystem.out.println(“Person - initialize executing!“);String s = String.valueOf(today.toLocaleString();setId(s); 然后把person.java和personLink.java这两个文件放到windchill/codebase/helloWorld/目录下进行编译。,模型扩展(续),写测试代码,public class HelloWorldTest public static void main(String args) String userName = args0;String pas
15、sword = args1;RemoteMethodServer methodserver = RemoteMethodServer.getDefault();methodserver.setUserName(userName);methodserver.setPassword(password);HelloWorldTest test = new HelloWorldTest();test.test(); ,模型扩展(续),测试代码,public void test() try Person p = Person.newPerson(); p.setName(“111“); p.setTit
16、le(“222“); p.setAge(1111); p = (Person) PersistenceHelper.manager.save(p); WTPart part = getPartByNumber(“D3_0000000064“); if(part=null) Debug.P(“part is null“); return; PersonLink link = PersonLink.newPersonLink(part, p); link = (PersonLink) PersistenceHelper.manager.save(link); if(link=null) Debug
17、.P(“link is null“); return; WTPart part1 = link.getUse(); Person p1 = link.getUsed(); if(part1=null) Debug.P(“part1 is null“); else Debug.P(“part1 is “+part1.getNumber(); if(p1=null) Debug.P(“p1 is null“); else Debug.P(“p1 is “+p1.getName(); catch(Exception e) e.printStackTrace(); ,模型扩展(续),public st
18、atic WTPart getPartByNumber(String number)WTPart part = null;tryQuerySpec qs = new QuerySpec(WTPart.class);SearchCondition sc = new SearchCondition(WTPart.class, WTPart.NUMBER, “=“, number);qs.appendWhere(sc);QueryResult qr1 = PersistenceHelper.manager.find(qs);while(qr1.hasMoreElements()part = (WTP
19、art)qr1.nextElement();catch(Exception e)e.printStackTrace();return part; ,模型扩展(续),把这个测试类在windchill shell 中运行,运行结果为下图然后我们现在看下数据库中的情况,模型扩展(续),在person和personlink这两张表中都有了数据,测试结果正确 注意事项 在进行建模之前要对一些参数进行设置,也就是把rose的操作目录指向windchill的目录,开发目录介绍,WT_HOME,wtCustom,wtSafeArea,src,db,siteMod,ptcCurrent,ptcOrig,sql,
20、com,itbg,itbg,tasks,com,itbg,com,templates,loadfiles,loadXMLFiles,com,itbg,com,itbg,codebase,com,itbg,com,itbg,jsp,netmarkets,com,itbg,1、wtCustom 放入修改系统的rbInfo文件 2、wtSateArea 下的siteMod文件中放入修改后的系统文件,比如.jspf文件、html、xml;ptcCurrent文件放系统当前版本的文件;ptcOrig放系统最原始的文件ant -f bin/swmaint.xml installSiteChanges 3、
21、codebase是运行时目录,放编译后的.class文件、放WEB相关文件、放模板文件(.html) 4、src目录放客制化的源文件,放国际化.rbInfo文件。 5、tasks目录放系统服务文件.xml文件,Info*Engine配置文件 6、loadFiles目录,放置需要导入到系统的工作流、生命周期等 7、loadXMLFiles目录,放置配置系统的信息的.xml文件 8、DB目录,放置建立模型后生成的SQL语句,Windchill类的介绍,1.如何在系统中查找对象对应的类 2.如何通过类在数据库中查找相关的表,如何在系统中查找对象对应的类,打开类型管理器,选择部件,这个部件就对应了系统
22、中的一个对象,页面的右部就会显示这个类的具体信息,在名称这栏中的wt.part.WTPart就是系统中部件对应的类,wt.part是包名,WTPart就是类的名称,这个时候就可以在Eclipse中查看这个类有那些相关的函数,同时也可以到wt.part这个包中查看其它的一些类,这些类也都是和WTPart有关。,如何通过在系统中查找对象对应的类,系统中的业务对象在Rose模型中都可以看到相应的方法,系统类的设计,系统中的服务类设计为xxHelper.java文件和xxService.java是组合关系,系统中的所有业务对象对应的方法在对应的service中,通过xxHelper.serivce.方
23、法 部件操作:WTPartHelper.service.方法 文档操作:WTDocumentHelper.service.方法 EC操作:ChangeHelper2.service.方法 文件夹的操作:FolderHelper.service.方法 生命周期的操作:LifeCycleHelper.manager.方法 推进流程对象的操作:MaturityHelper.service.方法 通知机制对象的操作:NotificationHelper.service.方法 位号的操作:OccurrenceHelper.service.方法 参与者的操作:OrganizationServicesHel
24、per.manager.方法 版本的操作:VersionControlHelper.service.方法,如何通过类在数据库中查找相关的表,在类型管理器中定义的那些对象在数据库中都有相对应的表存在,表的名称也就是类的名称。 例如:部件对象的类名称是WTPart,则数据库中就对应了一张名为WTPart的表。 WINDCHILL的数据库中的一张表其实对应的就是系统中的一个类名,所以有很多开发可以以数据库的表为入手点,如果你知道系统中的某个信息是存储在数据库中的具体表中的时候,就可以根据表的名称去系统中查找相关的类,来获取你需要的数据,如何通过类在数据库中查找相关的表,上面就是数据库中WTPart的
25、表,这里面的数据在WTPart这个类中就可以获取,例如你如果想要获取一个部件的生命周期状态,数据库中对应的字段是STATESTATE这个字段,那么你就可以在在代码中通过part.getLifeCycleState().getDisplay()这个函数来获取,所以在学习WINDCHILL系统的开发的时候一定不能忽略数据库的作用。,Windchill各个包的介绍,Windchill各个包的介绍,Windchill各个包的介绍,Windchill各个包的介绍,Windchill中的Model简介,Document Customizers Windchill中的Model简介 Windchill Do
26、cument客制方法介绍 Windchill中UI介绍,Windchill各个业务对象的模型介绍,Windchill Document客制方法介绍,文档属性 在Windchill document中WTDocumentMaster和 WTDocument是两个主要对象: 在WTDocumentMaster中对于文件中所有的版本版序有相同的值。 如果文件已建立很多版本版序,当master改变时将影响所有的版本版序。 在 WTDocument每一个版序有不同的值对应,因此WTDocument的改变只影响一种版序。 如果想规定一个从一个版序到另一个版序变化的属性,则需要扩展 WTDocument。,
27、Windchill Document客制方法介绍,类型 枚举类型(值列表)领域,在windchill中让用户能够进行分类管理的文件 。 类型的值被定义在 wt.doc.DocumentTypeRB中。 如果有一个要求不显示doctype属性,只需要把类型管理中设置类型的实例化中的勾去掉即可,不可删除。,Windchill Document客制方法介绍,Department 在Windchill中允许用户选择区域,负责文件的管理 枚举类型 值都被定义在 wt.doc.DepartmentListRB中。,Windchill Document客制方法介绍,文件与文件之间的关系: 文件结构 : 一个
28、文件可以使用很多其它子文件,其下层子文件也可以被其它文件使用。(使用与被使用的关系)文件参考 :一个文件涉及的信息存在于其他文件中。(参考与被参考的关系),Windchill Document客制方法介绍,文件结构,Windchill Document客制方法介绍,文件參考,Windchill Document客制方法介绍,创建文件以及文件的主文档、删除文件 添加文件的附件、删除附件 文件的出库、入库以及修改主文档 文件下载 文件与文件之间创建关联(文件参考、文件结构),Windchill Document客制方法介绍,三种创建文件的构造方法: newWTDocument (); newWTD
29、ocument(WTDocumentMaster master) ; newWTDocument(String number,String name, DocumentType type),Windchill Document客制方法介绍,創建文件實例 WTDocument newDoc = null; newDoc = WTDocument.newWTDocument(); newDoc.setName(“创建主文档22“);/文件的名称必设项 newDoc.setNumber(“888822“);/文件编号必设项 newDoc.setDepartment(DepartmentList.to
30、DepartmentList(“ENG“); /设置departmentlist即文件所属的部门,必设项 DocumentType doctype =DocumentType.toDocumentType(“$Document“); /必设项,文件类型为一般文件 newDoc.setDocType(doctype); setType(newDoc,“wt.doc.WTDocument|com.elead.Drawing“); newDoc = (WTDocument)PersistenceHelper.manager.save(newDoc); /保存文件,Windchill Document
31、客制方法介绍,以上只是对文件的基本信息进行了设置也就相当在创建文件的模板中只 是填写了基本信息没有上传文档时生成的不含主文档的文件。以下是创 建主文档:ContentHolder contentHolder =ContentHelper.service.getContents(newDoc); /获得文件的ContentHolder ApplicationData appdata = ApplicationData.newApplicationData(contentHolder); appdata.setRole(ContentRoleType.PRIMARY); 通过Application
32、Data 去设置主文档的名称、大小、以及文件上传路径等.ContentServerHelper.service.updateContent (contentHolder,appdata,fileStream);/主文档创建成功 参数fileStream是要上传的文件输入流。,Windchill Document客制方法介绍,删除文件 只删除主文档 ContentHolder contentHolder=ContentHelper.service.getContents(newDoc); ContentItem contentitem = ContentHelper.getPrimary(For
33、matContentHolder)contentHolder); ContentServerHelper.service.deleteContent(contentHolder,contentitem); 删除文件和主文档都删除 PersistenceHelper.manager.delete(doc);,Windchill Document客制方法介绍,添加附件 文件添加附件和文件添加主文档方法类似,唯一不同的就是 ContentRoleType类型。 主文档的类型是ContentRoleType. PRIMARY 附件的类型是ContentRoleType.SECONDARY,Windch
34、ill Document客制方法介绍,刪除附件 ContentHolder contentHolder=ContentHelper.service.getContents(doc); Vector vData =ContentHelper.getApplicationData(contentHolder); if (vData != null ,Windchill Document客制方法介绍,文件出库入库 为什么要对文件出库入库? 什么情况下对文件进行出库入库?对文件的出库主要的目的之一是为了防止一个文件同时两个人修改,由此可以看出只要是和文件更新相关的操作都要对文件进行出库,然后对出库后的
35、副本进行更新操作,最后入库。,Windchill Document客制方法介绍,文件出库 文件出库时, Windchil会自动将一个工作复本放入資料夾中的 Checked Out文件夹中。首先得到文件夹中的checkout文件夹:Folder myFolder = WorkInProgressHelper.service.getCheckoutFolder();然后对文件出库放入checkout文件夹中:CheckoutLink checkout_link = WorkInProgressHelper.service.checkout(doc, myFolder, “”);最后得到工作复本:d
36、oc = (WTDocument) checkout_link.getWorkingCopy();,Windchill Document客制方法介绍,出库实例 if (!wt.vc.wip.WorkInProgressHelper.isCheckedOut(Workable) doc) /判断文件是不是出库状态 if (!FolderHelper.inPersonalCabinet(CabinetBased) doc) ,Windchill Document客制方法介绍,文件的入库 对文件复本进行入库: updateDoc =(WTDocument)WorkInProgressHelper.s
37、ervice.checkin(updateDoc, comment); 参数updateDoc出库的副本文件; comment入库时的版序注解,Windchill Document客制方法介绍,入庫實例 WTDocument updateDoc = null; if (wt.vc.wip.WorkInProgressHelper.isCheckedOut(Workable) doc) if(WorkInProgressHelper.isWorkingCopy(doc)updateDoc = doc;elseupdateDoc = (WTDocument) WorkInProgressHelpe
38、r.service.workingCopyOf(doc);updateDoc = (WTDocument) WorkInProgressHelper.service.checkin(updateDoc, comment);PersistenceHelper.manager.refresh(updateDoc); elseupdateDoc = (WTDocument) WorkInProgressHelper.service.checkin(updateDoc, comment); ,Windchill Document客制方法介绍,修改主文檔 主文档的修改是主文档的删除和创建组合,在修改主文
39、档时应该 找到原来的主文档删除之后再创建新的主文档。具体实例见前面的主文档创建和删除方法。,Windchill Document客制方法介绍,文件下载 首先得到要下载文件的最新版本 ( Iterated iter = null; boolean flag = false; LatestConfigSpec latestconfigspec = new LatestConfigSpec(); QueryResult queryresult =ConfigHelper.service.filteredIterationsOf(master, latestconfigspec); while (qu
40、eryresult.hasMoreElements() ),Windchill Document客制方法介绍,然后取得文件的主文档或附件下载 ContentHolder contentholder = ContentHelper.service.getContents(downDOC); ContentItem contentitem = ContentHelper.getPrimary(FormatContentHolder) contentholder);/得到主文档 ApplicationData applicationdata = (ApplicationData) contentit
41、em; ContentServerHelper.service.writeContentStream(applicationdat a, sourcePath); 参数Applicationdata是下载的文件, 参数sourcePath为下载文件要存放的路径和文件名。,Windchill Document客制方法介绍,文件的关联-文件结构 文件与文件的使用关系创建(删除类似): 首先 判断有没有关联,得到文件之间关联是通过: PersistenceHelper.manager.find();查找得到;然后创建uselink关联: WTDocumentUsageLink usageLink =
42、 WTDocumentUsageLink.newWTDocumentUsageLink(WTDocument,WTDocumentMaster); PersistenceServerHelper.manager.insert(usageLink); /关联创建成功,Windchill Document客制方法介绍,文件的关联-文件参考 文件与文件之间参考关系的创建(删除类似): 首先查看是不是两者之间已有此关系: WTDocumentHelper.service.getDependsOnWTDocuments(WTDocum ent); 其次创建DependencyLink关联: WTDocu
43、mentDependencyLink.newWTDocumentDependencyLink(WTDocument,WTDocument); 最后把创建的关联插入数据库: PersistenceServerHelper.manager.insert(WTDocumentDependencyLink);,Windchill Document客制方法介绍,/* 获取一个文档的各个大版本的最新小版本* param docNumber String对象,就是获取这个编码对应的对象的各个大版本的最新小版本* return Vector对象,这个对象中的元素都是WTDocument类型的*/public
44、static Vector getDocMaxVersion(WTDocuemntMaster docMaster) throws WTException Vector v=new Vector();QueryResult qr1 = VersionControlHelper.service.allVersionsOf(docMaster);while(qr1.hasMoreElements()Object obj = qr1.nextElement();if(VersionControlHelper.isLatestIteration(Iterated) obj)v.add(obj);ret
45、urn v;,Windchill Document客制方法介绍,修改WTDocument的编码、名称方法: WTDocumentHelper.service.changeWTDocumentIdentity( existDocument, name, number, null); doc = (WTDocument) PersistenceHelper.manager.save(doc); 修改EPMDocument的名称、编码方法: Identified identified = (Identified) epm.getMaster(); EPMDocumentMasterIdentity
46、epmMI = (EPMDocumentMasterIdentity) identified.getIdentificationObject(); epmMI.setName(cadName); epmMI.setNumber(newNumber); IdentityHelper.service.changeIdentity(identified, epmMI); PersistenceHelper.manager.refresh(epm);,Windchill Document客制方法介绍,/* 設定文档檔狀態* param epm* return*/public String setDoc
47、umentState(WTObject obj) try State state = State.toState(“RELEASED“);String lifeState=“;if(obj instanceof EPMDocument)EPMDocument tempEPM=(EPMDocument)obj;lifeState=tempEPM.getLifeCycleState().toString();obj=tempEPM;if(obj instanceof WTDocument)WTDocument tempDoc=(WTDocument)obj;lifeState= tempDoc.g
48、etLifeCycleState().toString();obj=tempDoc;if(!lifeState.equals(“RELEASED“)LifeCycleHelper.service.setLifeCycleState(LifeCycleManaged) obj,state);return “1“; catch (WTException ex) ex.printStackTrace();return “setEPMDocumentState error:“ + ex.toString();return “;,Windchill Document客制方法介绍,通过EPMDocumen
49、t得到相应的推进流程 WTHashSet epmHashSet = new WTHashSet(); epmHashSet.add(epm); WTCollection collection=MaturityHelper.service.getPromotionNotices(epmHashSet); Object promoteObject = collection.toArray(); for (int i = 0; i promoteObject.length; i+) / 將WTSe中的元素取出String assnotice = (String) promoteObjecti.toString();ReferenceFactory referencefactory = new ReferenceFactory();PromotionNotice pn = (PromotionNotice) referencefactory.getReference(assnotice).getObject(); ,