高度なカスタマイズ > サービスおよびインフラストラクチャのカスタマイズ > システム生成 > ビジネスオブジェクトのモデル化
  
ビジネスオブジェクトのモデル化
* 
このガイドのコード例には、ガイドに掲載するために、行番号、非表示の編集記号 (タブや行末文字など) や余分なスペースが含まれているなど、実際とは多少異なるものもあります。このマニュアルから切り取りおよび貼り付けを行った場合は、アプリケーション内でサンプルとして使用する前に、それらの文字がないか確認して、除去してください。
Windchill 永続の概要
Windchill 永続アーキテクチャでは、Java のクラスおよびフィールドがデータベースの行および列にマッピングされています (スキーマ)。モデル化は、スキーマを説明する方法であり、Java ソースファイルのクラス宣言に、プロパティ、関連付け、およびその他のメタデータを説明するためのアノテーションメンバーを含む PTC の GenAs アノテーションを付けることによって行われます。
Java のアノテーションプロセッサは、javac のコンパイル中に呼び出され、フィールド、アクセッサ、RMI/PDS 外部化 API、およびその他のメソッド (equals()hashCode() など) を生成します。データベーススキーマ (テーブル、列、およびインデックス) を表す SQL スクリプトは、コンパイル後に個別に生成されます。
Java コンパイラは、必要なコンポーネントを生成し、コンパイルして、モデルをアノテーションによって宣言されているように実装するだけではなく、実行時にモデルのイントロスペクションを行うために必要な情報を生成します。これは、クラス (modelRegistry.properties)、関連付け (associationRegistry.properties)、およびそれらの階層 (descendentRegistry.properties) を登録し、実行時のイントロスペクションで使用される ClassInfo ファイルを生成します。
Jython
Jython は、広く使用されている Python プログラミング言語の Java 実装です。この章では、Jython は現実的なシナリオの例を示す実用的なコードを提供するために使用されています。Jython の動的な特性は、(Java プログラムと比べて) 非常に効果的に活用できます。Jython のインタープリタは、コンパイルされたコードやデバッガでは不可能な対話性と拡張性を提供します。さらに、Jython は Python 実装ですが (Java 上の)、Java プログラマはその構文をすぐに習熟できます。また、この構文は即座に変換できます。
Jython は http://jython.org で入手できます。
* 
Jython の使用例は、Windchill CLASSPATH が (<load point>/Windchill/bin シェルを呼び出すことによって起動できる) Windchill シェル内で実行する場合にすぐに使用できることを前提としています。
テーブルのモデル化
モデル化されたクラスの構造 (GenAsPersistable)
まず、シンプルで機能的な例を示します。この例は、この章のほかのセクションからも参照します。
リスト 1: SimpleExample.java
01 package com.acme.example;
02
03 import wt.fc.InvalidAttributeException;
04 import wt.fc.WTObject;
05 import wt.inf.container.WTContained;
06 import wt.util.WTException;
07 import wt.util.WTPropertyVetoException;
08
09 import com.ptc.windchill.annotations.metadata.*;
10
11 @GenAsPersistable(superClass=WTObject.class,
interfaces={WTContained.class},
12 properties={
13 @GeneratedProperty(name="name", type=String.class,
14 constraints=@PropertyConstraints(required=true))
15 })
16 public class SimpleExample extends _SimpleExample {
17 static final long serialVersionUID = 1;
18
19 public static SimpleExample newSimpleExample() throws WTException {
20 final SimpleExample instance = new SimpleExample();
21 instance.initialize();
22 return instance;
23 }
24
25 @Override
26 public void checkAttributes() throws InvalidAttributeException {
27 super.checkAttributes();
28 try {
29 nameValidate(name);
30 } catch (WTPropertyVetoException wtpve) {
31 throw new InvalidAttributeException(wtpve);
32 }
33 }
34 }
_SimpleExample を拡張するクラス SimpleExample (行番号 16) が定義されています。このクラスには GenAsPersistable アノテーション (行番号 11 から 15) が付けられています。これは、このクラスがデータベース内でテーブルとして永続化されることを示します。このクラスには、(必須の) 文字列である name というプロパティ (行番号 13 から 14) が 1 つあります。さらに、静的なファクトリメソッド (行番号 19 から 23) と checkAttributes() メソッドのオーバーライド (行番号 25 から 33) が 1 つずつ実装されています。
_SimpleExample のソースは次のとおりです。
GenAsPersistable アノテーションのアノテーションプロセッサによって親クラスが生成されます (厳密には、後でコンパイラによってコンパイルされるソースファイルが生成されます)。
この親クラスは、name プロパティの実装 (照会定数、フィールド、ゲッター、セッター、およびセッターの検証) を提供するだけではなく、外部化ロジックやその他の必要なメソッドも提供します。
_ クラスは、リスト 2 に示されているフィールドとメソッドで構成されます。
リスト 2: _SimpleExample javap の結果
01 public abstract class com.acme.example._SimpleExample extends wt.fc.WTObject implements wt.inf.container.WTContained,java.io.Externalizable{
02 static final long serialVersionUID;
03 static final java.lang.String RESOURCE;
04 static final java.lang.String CLASSNAME;
05 public static final java.lang.String NAME;
06 static int NAME_UPPER_LIMIT;
07 java.lang.String name;
08 wt.inf.container.WTContainerRef containerReference;
09 public static final long EXTERNALIZATION_VERSION_UID;
10 public com.acme.example._SimpleExample();
11 public java.lang.String getName();
12 public void setName(java.lang.String) throws wt.util.WTPropertyVetoException;
13 void nameValidate(java.lang.String) throws wt.util.WTPropertyVetoException;
14 public java.lang.String getContainerName();
15 public wt.inf.container.WTContainer getContainer();
16 public wt.inf.container.WTContainerRef getContainerReference();
17 public void setContainer(wt.inf.container.WTContainer) throws wt.util.WTPropertyVetoException, wt.util.WTException;
18 public void setContainerReference(wt.inf.container.WTContainerRef) throws wt.util.WTPropertyVetoException;
19 void containerReferenceValidate(wt.inf.container.WTContainerRef) throws wt.util.WTPropertyVetoException;
20 public java.lang.String getConceptualClassname();
21 public wt.introspection.ClassInfo getClassInfo() throws wt.introspection.WTIntrospectionException;
22 public java.lang.String getType();
23 public void writeExternal(java.io.ObjectOutput) throws java.io.IOException;
24 protected void super_writeExternal_SimpleExample(java.io.ObjectOutput) throws java.io.IOException;
25 public void readExternal(java.io.ObjectInput) throws java.io.IOException, java.lang.ClassNotFoundException;
26 protected void super_readExternal_SimpleExample(java.io.ObjectInput) throws java.io.IOException, java.lang.ClassNotFoundException;
27 public void writeExternal(wt.pds.PersistentStoreIfc) throws java.sql.SQLException, wt.pom.DatastoreException;
28 public void readExternal(wt.pds.PersistentRetrieveIfc) throws java.sql.SQLException, wt.pom.DatastoreException;
29 boolean readVersion6009937787959182077L(java.io.ObjectInput, long, boolean) throws java.io.IOException, java.lang.ClassNotFoundException;
30 protected boolean readVersion(com.acme.example.SimpleExample,
java.io.ObjectInput, long, boolean, boolean) throws java.io.IOException,
java.lang.ClassNotFoundException;
31 protected boolean super_readVersion_
SimpleExample
(com.acme.example._SimpleExample, java.io.ObjectInput, long, boolean, boolean) throws java.io.IOException, java.lang.ClassNotFoundException;
32 boolean readOldVersion(java.io.ObjectInput, long, boolean, boolean) throws java.io.IOException, java.lang.ClassNotFoundException;
33 static {};
34 }
このアノテーションは、後でコンパイラによって実装される宣言で構成されています。name のすべての要素を手動で実装する代わりに、これがアノテーション内でプロパティとして宣言され、_ 親ファイルがすべての必要なコンポーネントを実装します。リスト 3 は、required=truenameValidate() メソッドに対する効果の例を示しています。
リスト 3: nameValidate() の断片
01 if (name == null || name.trim().length() == 0)
02 throw new wt.util.WTPropertyVetoException("wt.fc.fcResource", wt.fc.fcResource.REQUIRED_ATTRIBUTE,
03 new Object[] { new wt.introspection.PropertyDisplayName (CLASSNAME, "name") },
04 new java.beans.PropertyChangeEvent(this, "name", this.name, name));
superClassinterfaces (リスト 1 の行番号 11) の目的は次のとおりです。
superClass アノテーションメンバーはシンプルであり、extends_ クラスによって吸収されています。これにより、モデル化された要素をコードにして、クラスに組み込むことができます。したがって、"実際の" (論理的な) 親 (ここでは WTObject) を指定できるようにする superClass が必要です。これは、後で _ クラス (_SimpleExample) が自動的に拡張します (前述のとおり)。
interfaces アノテーションメンバーも同じような目的で使用されます。これは、実装するインタフェースを識別できるようにします。implements は同じように吸収されていませんが、さまざまな技術的観点から、アノテーションメンバーを使用することは、実装を直接使用することよりも効果的で、論理にかなっています。この例は WTObject を拡張し、WTContained を実装します。コンパイラは public class <X> extends _<X> { ... } 構文を適用するので、この構文が使用されていなければ、コンパイラでコンパイルエラーが発生します。
ファクトリパターン (リスト 1 の行番号 19 にある newSimpleExample()) が使用されていることに注目してください。Windchill では、コンストラクタの代わりにこのパターンが使用されます。外部化では引数を取らないコンストラクタを使用してインスタンスが構築される必要があり、またこれを呼び出すための負担が最小限である必要があるからです。ファクトリパターンは、public static <X> new<X>(<args...>) throws WTException { ... } という形式の静的メソッドで構成され、アノテーションが付けられているファイルのコンストラクタの代わりに使用されます。ファクトリのボディは、例によって示されている形式に従っている必要があります。具体的には、次の処理を行う必要があります。
1. クラスの instance を、その (デフォルトの) 引数を取らないコンストラクタを使用して構築する。
2. (静的ではない) initialize メソッドを呼び出して、静的メソッドに指定されている引数を渡す。静的ファクトリが単独で引数を処理することはできません。サブクラスが静的メソッドの処理を利用できないからです (動作を継承できるようにすることが initialize メソッドの主な目的です)。独自の initialize メソッドを作成する必要がある場合があります (存在しない場合、または動作を補足する必要がある場合)。その場合、これは protected void initialize(args...) throws WTException という形式である必要があり、また super.initialize(...) を呼び出す必要があります。
3. instance を返します。
次のファクトリ/初期化ペアは、必要なプロパティが割り当てられるように name を受け取るファクトリメソッドを追加する適切な方法を示しています。
リスト 4: ファクトリ/初期化ペアの例
01 public static SimpleExample newSimpleExample(final String name) throws WTException {
02 final SimpleExample instance = new SimpleExample();
03 instance.initialize(name);
04 return instance;
05 }
06
07 protected void initialize(final String name) throws WTException {
08 super.initialize();
09 try {
10 setName(name);
11 } catch (WTPropertyVetoException wtpve) {
12 throw new WTException(wtpve);
13 }
14 }
さらに、serialVersionUID (リスト 1 の行番号 17) が必要です。Windchill が外部化ロジック (必要に応じて古いバージョンのシリアル化解除を含む) を管理し、システムによって割り当てられたシリアルバージョン UID がこのロジックを破断するからです。ここでも、これが提供されていなければ、コンパイラでコンパイルエラーが発生します。
最後に、checkAttributes() は、生成されたフィールドとメソッド (リスト 1 の行番号 29) が使用されていることを示すためだけに役立ちます。特に、namenameValidate() は、アノテーションが付けられているクラスにアクセスすることを許可するだけのデフォルトのアクセス設定で生成されます。
コンパイル
コンパイルについては、com.ptc.windchill.annotations.metadata パッケージの Javadoc で詳しく説明されていますが、SimpleExample のカスタマイズは、次のステップを実行することによってコンパイルし、組み込むことができます。
1. ロードポイント (たとえば /opt/ptc/Windchill) に cd で移動します。
2. bin/windchill shell を呼び出して、windchill シェルを起動します。
3. mkdir -p src/com/acme/example を実行して、src/com/acme/example ディレクトリを作成します。
4. このディレクトリに SimpleExample.java を作成し、これに上記の例の内容を含めます。
5. ant -f bin/tools.xml class -Dclass.includes=com/acme/example/* を実行して、この例をコンパイルします (このコマンドはロードポイントディレクトリで実行する必要があります)。
6. ant -f bin/tools.xml sql_script -Dgen.input=com.acme.example.* を実行して、SQL スクリプトを生成します。
7. SQL スクリプト create_SimpleExample_Table.sql を見つけ (db 内にあります)、ロードします。
8. create_SimpleExample_Index.sql についても同じステップを繰り返します。
9. MethodServer を起動または再起動します。
リスト 5 に示されているように、Jython を使用すると、この例を素早く検証できます。
リスト 5: SimpleExample の永続化
01 from wt.fc import PersistenceHelper
02 from com.acme.example import SimpleExample
03
04 se = SimpleExample.newSimpleExample()
05 se.setName('test')
06 se = PersistenceHelper.manager.store(se)
プロンプトが表示されたら、システム管理者としての認証情報を入力します。オブジェクトがサイトコンテナに作成されます。これは、sn.getContainer().getName() を実行することによって確認できます。setName(’test’) が別個に呼び出されていますが、これは、引数として name を使用してファクトリ/初期化メソッドを作成した場合には必要ありません。
クラスのテーブルと列へのマッピング
この例では SimpleExample のインスタンスが永続化されたので、テーブルに行が 1 つ追加されています。テーブルの詳細をリスト 6 に示します。
リスト 6: create_SimpleExample_Table.sql
01 exec WTPK.dropTable('SimpleExample')
02 set echo on
03 REM Creating table SimpleExample for com.acme.example.SimpleExample
04 set echo off
05 CREATE TABLE SimpleExample (
06 classnamekeycontainerReferen VARCHAR2(600),
07 idA3containerReference NUMBER,
08 name VARCHAR2(600) NOT NULL,
09 createStampA2 DATE,
10 markForDeleteA2 NUMBER NOT NULL,
11 modifyStampA2 DATE,
12 classnameA2A2 VARCHAR2(600),
13 idA2A2 NUMBER NOT NULL,
14 updateCountA2 NUMBER,
15 updateStampA2 DATE,
16 CONSTRAINT PK_SimpleExample PRIMARY KEY (idA2A2))
17 STORAGE ( INITIAL 20k NEXT 20k PCTINCREASE 0 )
18 ENABLE PRIMARY KEY USING INDEX
19 TABLESPACE INDX
20 STORAGE ( INITIAL 20k NEXT 20k PCTINCREASE 0 )
21 /
22 COMMENT ON TABLE SimpleExample IS 'Table SimpleExample created for com.acme.example.SimpleExample'
23 /
24 REM @//com/acme/example/SimpleExample_UserAdditions
テーブルの名前は、クラスの名前を反映します。これは変更できます。詳細については、アノテーションメンバー tableProperties および関連付けられているメンバー tableName の Javadoc を参照してください。列のうち、name については内容が誰にでもすぐにわかりますが、その他の列についてはそうとはかぎりません。WTContained であることに基づいて取得された classnamekeycontainerReferen 列と idA3containerReference 列には、コンテナへの参照が格納されています。その他の列は、Persistable であることに基づいて取得されました。これは、Windchill クラスをテーブルとして永続化するためのトップレベルインタフェースです。
モデル化された関連付け (GenAsBinaryLink)
クラスをテーブルにマッピングするためのアノテーションは 2 つあり、1 つは GenAsPersistable で、もう 1 つは GenAsBinaryLink です。これは、2 つの永続オブジェクト (2 つのテーブルの行) を相互にリンクする関連付けを表します。各バイナリリンクは、役割 A と役割 B の 2 つの役割で構成されます。
SimpleExamples のグラフを作成できます。このグラフでは、SimpleExample に複数の親と子を設定できます。
リスト 7: SimpleExampleLink.java
01 package com.acme.example;
02
03 import wt.fc.ObjectToObjectLink;
04 import wt.util.WTException;
05
06 import com.ptc.windchill.annotations.metadata.*;
07
08 @GenAsBinaryLink(superClass=ObjectToObjectLink.class,
09 roleA=@GeneratedRole(name="parent", type=SimpleExample.class),
10 roleB=@GeneratedRole(name="child", type=SimpleExample.class))
11 public class SimpleExampleLink extends _SimpleExampleLink {
12 static final long serialVersionUID = 1;
13
14 public static SimpleExampleLink newSimpleExampleLink
(final SimpleExample parent, final SimpleExample child)
throws WTException {
15 final SimpleExampleLink instance = new SimpleExampleLink();
16 instance.initialize(parent, child);
17 return instance;
18 }
19 }
これは、同様にコンパイルすると、リスト 8 に示すように、Jython で検証できます。
リスト 8: SimpleExampleLink の永続化
01 from wt.fc import PersistenceHelper
02 from com.acme.example import *
03
04 parent = SimpleExample.newSimpleExample()
05 parent.setName('parent')
06 parent = PersistenceHelper.manager.store(parent)
07
08 child = SimpleExample.newSimpleExample()
09 child.setName('child')
10 child = PersistenceHelper.manager.store(child)
11
12 l = PersistenceHelper.manager.store(SimpleExampleLink.
newSimpleExampleLink (parent, child))
SimpleExample の場合と同じように、ファクトリメソッドが使用されます (リスト 7 の行番号 14 から 17)。ただし、リンクは常に 2 つのオブジェクトを関連付けるので、ファクトリメソッド (および関連付けられている initialize メソッド) は役割 A と役割 B を引数として受け取ります。
モデリング列
モデリング列
GenAsPersistableGenAsBinaryLink は、データベース列を指定するためのメカニズムを 3 つ提供します。
1. properties (GeneratedProperty の配列) は、文字列、数値、ブールなどを表します。
2. foreignKeys (GeneratedForeignKey の配列) は、ほかの永続オブジェクトを参照します (および、クラス名/キーペアとして保存されます)。
3. roleA/roleB (GenAsBinaryLink のみ) は、関連付けに使用される外部キーの特殊な形式です。
さらに、derivedProperties (DerivedProperty の配列) は、プロパティと外部キーにコンビニエンスアクセッサを提供します。
これは、一連のプロパティを集めて独自のクラスにするために便利です。このクラスは、1 つのエンティティとして管理し、1 つの永続オブジェクトに統合することができます。GenAsObjectMappable アノテーションは、この目的のために使用されており、Windchill の cookie で広く活用されています。GenAsObjectMappable アノテーションが付けられたクラスが GeneratedProperty のタイプとして指定されると、そのすべてのプロパティがオーナークラスのテーブルの列になります。名前の競合を防止するために、名前は難解なアルゴリズムによって決定される文字/数字パターンを使用して "管理" されます。idA3containerReferenceidA3Persistable.thePersistInfo.theObjectIdentifier.id がマッピングされている idA2A2 は、このマングリングによって生成されています。
GeneratedProperty
SimpleExampleGeneratedProperty (必須で String) タイプの name) の例はすでに示しました。GeneratedProperty では、生成と動作を制御するためのアノテーションメンバーを多数使用できます。詳細については、Windchill の Javadoc を参照してください。
GeneratedForeignKey
外部キーは、モデル化されておらず、WTContained から継承されています。
リスト 9: コンテナ定義の断片
01 @GeneratedForeignKey(name="ContainerLink",
02 foreignKeyRole=@ForeignKeyRole(name="container", type=wt.inf.container.WTContainer.class, referenceType=wt.inf. container.WTContainerRef.class, supportedAPI=SupportedAPI.PRIVATE,
03 constraints=@PropertyConstraints(required=true)),
04 myRole=@MyRole(name="contents", supportedAPI=SupportedAPI.PRIVATE))
SimpleExample のスキーマに対するコンテナ参照の影響として、2 つの列が生成されています (前述)。実際に、これをさらにひも解くと、これらのフィールドは GenAsObjectMappable である WTContainerRef から ObjectReference を介して取得されていることがわかります。外部キーは "単なる" 別のプロパティであると言えますが (実際に、プロパティを一種の ObjectReference でタイプとしてモデル化して、(作成される列の観点からは) "同じ" 結果を達成できます)、Windchill 永続レイヤーは外部キーを一種の関連付けとして認識するため、それらをユーザーに代わって管理できます。その主な利点は、以下のとおりです。
owner=false を設定することによって、foreignKeyRole オブジェクトが (関連付けの一部である場合に) 削除されることを防止できます。
cascade=true を設定することによって、foreignKeyRole オブジェクトが削除されるときに myRole が削除されるようにできます。
cascade=false (デフォルト値) のときに役割 foreignKeyRole が削除されると、myRole によって保持されている参照が自動的に解除されます。
参照のアクセッサだけではなく、自動的に生成される参照先のオブジェクトのアクセッサも取得できます。
autoNavigate=true を設定することによって、(required=true の場合に) 参照先のオブジェクトを自動的に読み込むことができるので、参照先のオブジェクトにアクセスするときに、ほかのデータベースにヒットすることを防止できます。
外部キーリンクを、ほかのバイナリリンクとまったく同じようにナビゲートできます。
GeneratedForeignKey は、所定の永続オブジェクトが "多くとも" 1 つのほかの永続オブジェクトに関連付けられている場合に使用されます。WTReference の具象サブタイプの GeneratedProperty ではなく GeneratedForeignKey を使用するようにしてください。GeneratedForeignKey を使用すると、Windchill 永続アーキテクチャで参照を関連付けとして管理できるからです。ただし、これには例外がいくつかあります。特に、WTPrincipals (ユーザー) との関連付けは、GeneratedForeignKey としてではなく、WTPrincipalReference タイプの GeneratedProperty としてモデル化される必要があります。これは、関連付けを管理する必要がないからであり (ユーザーは削除できません)、また参照のアクセッサ "のみ" が必要であるからです (これにはユーザーに関する必要な情報がすべて含まれています)。
* 
GeneratedRoles とまったく同じように、作業版数のマスターを拘束するために一般的に行われている方法で、既存の (親クラス/インタフェースでモデル化されている) 外部キーを拘束できます。外部キーを拘束するとき、継承元の外部キーの値と異なる値を指定する必要があるだけで、親のすべてのプロパティを再度指定する必要はありません。
GeneratedRole
GeneratedRole アノテーションは、SimpleExampleLink で説明した GenAsBinaryLink の役割 A と役割 B について説明するために使用されます。役割は、リンクを 2 つの永続オブジェクトに関連付ける特殊な外部キーとして考えることができます (役割には外部キーと同じ継承機能があります)。外部キーは、関連付けられている役割の多重度が 0 から 1 であり、関連付けが追加のデータ (プロパティ) を必要としない場合にのみ適用可能である一方、バイナリリンクは、関連付けが多対多である場合、関連付けにプロパティがある場合、または関連付けがその他の方法で PTC ビジネスオブジェクトで永続化される場合 (既存の PTC クラスは変更できないため) に適用可能です。
DerivedProperties
派生プロパティそのものは永続化されませんが、派生プロパティは永続プロパティにコンビニエンスアクセッサ (ゲッター、セッター、および照会定数) を提供します。これがなければ、cookie 内または外部キー参照間にある永続プロパティを識別できなくなります。c というフィールドが b という cookie 内で識別できなくなっており、この cookie 自体も現在のクラスのプロパティである a という cookie 内で識別できなくなっているとします。
これには、これらの cookie が初期化されていない場合に発生する可能性のある NullPointerExceptions に注意しながら、this.getA().getB().getC() を使用することによってアクセスできます。または、単純にこの派生プロパティをクラスに追加し、すべての処理 (NullPointerException の処理を含む) が自動的に行われるようにすることもできます。
リスト 10: a.b.c 派生プロパティ
@DerivedProperty(name="c", derivedFrom="a.b.c")
この派生プロパティを使用して、this.getC() を呼び出すことができます。
関連付けられているオブジェクトのフィールドに外部キーを介してアクセスする必要がある場合は、外部キーの名前の後ろに . ではなく > を区切り記号として追加します。関連付けられている mastername に直接アクセスするために、WTPart は次の派生プロパティに依存します。
リスト 11: master>name 派生プロパティ
@DerivedProperty (name="name " , derivedFrom="master>name " )
特殊な永続の構成
GenAsUnPersistable "テーブル"
データベーステーブルにマッピングされているものとして認識されるクラスはすべて、wt.fc.Persistable を拡張する必要があります。GenAsPersistable によって生成される _ クラスは、これを自動的に処理します。GenAsBinaryLink- によって生成される _ クラスは、Persistable を拡張する wt.fc.BinaryLink を実装することによってこれを行います。
永続クラスとして実装されるインタフェースをモデル化するとき、通常は、これらのアノテーションを使用して列 (プロパティ、外部キー、および役割) について説明しますが、実装 (具象) クラスを使用して列を表すこともできます。Windchill のドメインインタフェースではこのアプローチが使用されているため、一連のインタフェースを実装するだけで、処理中 (Workable) やライフサイクル管理 (LifeCycleManaged) などの重要なビジネスロジックを取得できます。
実装クラスでインタフェースのプロパティを永続化する場合は、インタフェースにアノテーションを付ける必要があります。ただし、すべてのインタフェースが常に永続クラスのみによって実装されることを前提としているわけではありません。まれに、インタフェースが永続クラスによって実装されていたり (データの永続化を可能にするためにインタフェースにアノテーションが付けられることが必要になる)、非永続クラスによって実装されていたり (そのクラスが Persistable になることを GenAsPersistableGenAsBinaryLink が確認することが問題になる) します。このようなケースは、GenAsUnPersistable アノテーションを使用して解決できます。永続実装クラスはインタフェースを自動的に永続インタフェースとして扱いますが、非永続実装クラスは無用に永続化されません。
永続クラスと同じように生成によるメリットを生かすため、非永続クラスに GenAsUnPersistable でアノテーションを付けることはできますが、必要ではありません。さらに、外部化ロジックが自動的に提供されるため、クラスが BLOB として永続化される場合には、このアノテーションを活用できます。これは、インスタンスを BLOB にするときに RMI 外部化が使用されるからです。"BLOB として永続化される" とは、クラス全体が永続クラスのテーブルの BLOB 列に保存されることを意味します。オブジェクトを BLOB にすることは回避してください。インスタンスが挿入された後にクラスが変更されている場合は特に、BLOB の読み直しが複雑であることを見落とすおそれがあるからです。wt.fc.NetFactor を実装するクラスを BLOB として保存する場合は、そのクラスを wt.util.Evolvable にする必要があります。
GenAsEnueratedType 列
Windchill では、個別のローカライズ可能な文字列セットのモデル化がサポートされています。Windchill にコンピュータモデルを保存し、それらを desktoplaptop、または server に分類するとします。これを行う方法は次のとおりです。
リスト 12: ComputerType.java
01 package com.acme.example;
02
03 import com.ptc.windchill.annotations.metadata.*;
04
05 @GenAsEnumeratedType
06 public class ComputerType extends _ComputerType {
07 public static final ComputerType DESKTOP = toComputerType("desktop");
08 public static final ComputerType LAPTOP = toComputerType("laptop");
09 public static final ComputerType SERVER = toComputerType("server");
10 }
リスト 13: ComputerTypeRB.rbInfo
01 ResourceInfo.class=wt.tools.resource.EnumResourceInfo
02
03 desktop.value=Desktop
04 desktop.order=10
05
06 laptop.value=Laptop
07 laptop.order=20
08 laptop.defaultValue=true
09
10 server.value=Server
11 server.order=30
これは、次のように GeneratedProperty を使用して Computer クラスに組み込むことができます。
リスト 14: コンピュータタイプの断片
01 @GeneratedProperty(name="type", type=ComputerType.class, initialValue="ComputerType.getComputerTypeDefault()",
02 constraints=@PropertyConstraints(upperLimit=20, required=true))
このクラスは、前述の一般的なフォーマットに従っています (その (生成された) _ クラスを拡張するアノテーション付きクラスです)。GenAsEnumeratedType でアノテーションが付けられているクラスは最終的には wt.fc.EnumeratedType を拡張し、見ておわかりのとおり、多数のメソッドが自動的に生成されます。その主なものに、to<X>(String)get<X>Default() があります (X はクラスの名前です)。すべてのメソッドを表示するには、javap com.acme.example._ComputerType を呼び出します。
リスト 12 の行番号 7 から 9 は、列挙タイプのインスタンスを生成するために toComputerType(...) API に依存する定数宣言です。これらのエントリは、同じディレクトリにある <X>RB.rbInfo という名前の対応する rbInfo ファイルに含まれている必要があります。この rbInfo ファイルは ResourceInfo.class=wt.tools.resource.EnumResourceInfo タイプであり、ローカリゼーションと値の順序付けの両方をサポートしています。
この列挙タイプを GeneratedProperty として組み込みます。initialValue と拘束が使用されていることに注目してください。すべてのコンピュータモデルが 3 つのタイプのいずれかに割り当てられる必要があります。デフォルトのタイプは laptop です。列挙タイプは、単純な文字列として保存 (およびシリアル化) されます (この場合、保存値は desktoplaptop、または server のいずれかになります)。文字列のデフォルトの upperLimit は 200 文字で、かなり長いので (詳細については Javadoc を参照)、より現実的な最大文字数を設定します。
rbInfo ファイルを構築するには、ant -f bin/tools.xml bundle -Dbundle.input=com.acme.example.* を実行します。拡張子は rbInfo である必要があり、大文字と小文字は区別されます。"I" が小文字であれば、バンドルターゲットはこのファイルを無視します。
GenAsPrimitiveType 列
wt.fc.EnumeratedType の Javadoc を参照すると、EnumeratedTypeGenAsPrimitiveType でアノテーションが付けられています。また、アノテーションの唯一の引数は String.class です。
GenAsPrimitiveType アノテーションはシンプルなアノテーションであり、単一の値を必要とします。これは "プリミティブ" タイプと呼ばれ、アノテーション付きクラスが (永続とシリアル化のために) 縮小されたものです。これを使用することはまずありませんが、これは、簡素なフィールドの機能を拡張するクラス (ロジック) を構築する場合のために用意されています。これを使用する場合は、アノテーションの一部としてこのクラスが縮小されて生成されるタイプを指定する必要があるだけではなく、プリミティブタイプを受け取るコンストラクタと現在の値を返すための <type-in-lower-case>Value() メソッドを提供する必要もあります。
詳細については、アノテーションの Javadoc を参照してください。
GenAsDatastoreSequence データベースシーケンス
工場出荷時設定の Windchill は、部品番号とドキュメント番号を自動的に割り当てます。これは、データベースシーケンスを使用して行われます。
リスト 15: MySequence.java
01 package com.acme.example;
02
03 import com.ptc.windchill.annotations.metadata.*;
04
05 @GenAsDatastoreSequence
06 public class MySequence extends _MySequence { }
前と同じように、SQL を生成およびロードする必要があります (また、アノテーション付きクラスを変更するたびに MethodServer を再起動する必要があります)。これが完了すると、次に示すように値を取得できます (次の例は、シーケンス値をまだ取得していないと想定して 1 と 2 を印刷します)。
リスト 16: シーケンス値の取得
01 from com.acme.example import MySequence
02 from wt.fc import PersistenceHelper
03
04 print PersistenceHelper.manager.getNextSequence(MySequence )
05 print PersistenceHelper.manager.getNextSequence(MySequence )
* 
GenAsDatastoreSequence は 4 つの GenAsDatastore アノテーションのうちの 1 つです。
サービス
Windchill サービスには、モデル化されたビジネスオブジェクトを管理するための API とロジックが用意されています。Windchill サービスは、以下の要素で構成されます。
静的フィールド (一般的に servicemanager などの名前が付けられている、サービスを参照する静的フィールドを含む) およびメソッドで構成される (オプションの) ヘルパー。
リモートで呼び出すことができるメソッド宣言で構成されるサービスインタフェース。
サービスを実装しており、メソッドサーバーでサービスとして実行されるように登録されている標準サービス。
サービスについては、このドキュメントのほかのセクションで説明していますが、これが基本的なパターンです。
リスト 17: ExampleHelper.java
01 package com.acme.example;
02
03 import wt.services.ServiceFactory;
04
05 /** Helpers are not instantiated and should consist of only static
fields/methods **/
06 public final class ExampleHelper {
07 /** Use the ServiceFactory to acquire an instance of the service. **/
08 public static final ExampleService service = ServiceFactory.
getService(ExampleService.class);
09 }
リスト 18: ExampleService.java
01 package com.acme.example;
02
03 import wt.method.RemoteInterface;
04 import wt.util.WTException;
05
06 /** RemoteInterface annotation is required for all service interfaces **/
07 @RemoteInterface
08 public interface ExampleService {
09 /** All interface methods are callable via RMI and must
throw WTException **/
10 SimpleExample createSimpleExampleByName(final String name)
throws WTException;
11 }
リスト 19: StandardExampleService.java
01 package com.acme.example;
02
03 import wt.fc.PersistenceHelper;
04 import wt.services.StandardManager;
05 import wt.util.WTException;
06 import wt.util.WTPropertyVetoException;
07
08 /** service must extend StandardManager, implement service interface **/
09 public class StandardExampleService extends StandardManager implements
ExampleService {
10 /** MethodServer refectively calls this API during startup **/
11 public static StandardExampleService newStandardExampleService()
throws WTException {
12 final StandardExampleService instance = new StandardExampleService();
13 instance.initialize();
14 return instance;
15 }
16
17 @Override
18 public SimpleExample createSimpleExampleByName(final String name)
throws WTException {
19 final SimpleExample example = SimpleExample.newSimpleExample();
20 try {
21 example.setName(name);
22 }
23 catch (WTPropertyVetoException wtpve) {
24 throw new WTException(wtpve);
25 }
26 return (SimpleExample) PersistenceHelper.manager.store(example);
27 }
28 }
サービスはsite.xconf で登録されている必要があります。番号 99999 は既存のサービスを上書きしないよう一意の値である必要があります。site.xconf に対する変更は、xconfmanager を使用して適用する必要があります。すべてのカスタマイズサービスを site.xconf に登録する必要があります。
リスト 20: site.xconf のフラグメント
01 <Property name="wt.services.service.99999"
02 targetFile="codebase/wt.properties"
03 value="com.acme.training.MyService/com.acme.
training.StandardMyService"/>
このサービスを使用すると、SimpleExample を永続化するための Jython の例を次のように縮小できます。
リスト 21: サービスによる SimpleExample の永続化
01 from com. acme . example import
02
03 se = ExampleHelper.service.createSimpleExampleByName(’test’)
ローカライズ済みテキスト
ローカライズ済みテキストの例は、すでに示しました。ComputerTypeRB.rbInfo には、ComputerType の (デフォルトの英語の) テキストが含まれています。列挙タイプのローカライズ済みテキストを提供するだけではなく、クラス、フィールド名、およびメッセージ (例外メッセージなど) のローカライズも行います。
クラス名と属性名
イントロスペクションにより、クラスおよびプロパティの (ローカライズ済み) 表示名を取得するための API が提供されます。デフォルトの表示名は、次の Simple Example.Name を生成する例が示すように、値が明示的に指定されていない場合に計算されます。
リスト 22: SimpleExample の表示名
01 from wt.introspection import WTIntrospector
02 from com.acme.example import SimpleExample
03
04 snci = WTIntrospector.getClassInfo(SimpleExample)
05 print "%s.%s" % (snci.getDisplayName(), snci.getPropertyDisplayName
(snci.getPropertyDescriptor('name'), None))
SimpleName を Simple と表示し、SimpleName.name を aka と表示するとします。これを行うには、次のように、同じディレクトリに MetadataResourceInfo を作成します。
リスト 23: exampleModelRB.rbInfo
01 ResourceInfo.class=wt.tools.resource.MetadataResourceInfo
02
03 # Entry Format (values equal to default value are not included)
04 # <key>.value=
05 # <key>.category=
06 # <key>.comment=
07 # <key>.argComment<n>=
08 # <key>.constant=
09 # <key>.customizable=
10 # <key>.deprecated=
11 # <key>.abbreviatedDisplay=
12 # <key>.fullDisplay=
13 # <key>.shortDescription=
14 # <key>.longDescription=
15
16 # Entry Contents
17 SimpleExample.value=Simple
18 SimpleExample.name.value=aka
これらのバンドルは、列挙タイプに使用されるバンドルスタイルと似ており、同じ方法でコンパイルされます。コンパイルが完了すると、Jython スクリプトによって Simple.aka が生成されます。
メッセージ
クラス名とプロパティをローカライズするだけでは十分ではありません。ユーザーへのあらゆる通知もローカライズする必要があります (開発者は必ずしもユーザーではありません)。列挙タイプ、およびクラスとそのプロパティには rbInfo フォーマットが使用されます。一般的なメッセージ (通常、サービスによって報告される例外やステータスメッセージに含まれています) の場合は、最終的に java.util.ListResourceBundle を拡張する Java ソース/クラスファイルが使用されます。ListResourceBundle の契約が難解であるため、宣言型の WTListResourceBundle を使用します。例:
リスト 24: exampleResource.java
01 package com.acme.example;
02
03 import wt.util.resource.*;
04
05 /** This example blatantly plagiarized from the JavaDoc. **/
06 @RBUUID("com.acme.example.exampleResource")
07 public class exampleResource extends WTListResourceBundle {
08 @RBEntry("This is the localized text with a single substitution: \"{0}\".")
09 @RBComment("An example entry.")
10 @RBArgComment0("Any string...")
11 public static final String EXAMPLE_STRING = "0";
12 }
これにより、メッセージまたは例外が生成されます。
リスト 25: exampleResource を使用したメッセージ
01 from com.acme.example import exampleResource
02 from wt.util import WTException, WTMessage
03
04 print WTMessage(exampleResource.getName(), exampleResource.EXAMPLE_STRING,
['substitution']).getLocalizedMessage()
05
06 raise WTException(exampleResource.getName(), exampleResource.EXAMPLE_STRING,
['substitution'])
最初の呼び出しによって This is the localized text with a single substitution: ‘‘substitution’’ が生成され、次の呼び出しによって wt.util.WTException: (com.acme.example.exampleResource/0) wt.util.WTException: This is the localized text with a single substitution: ‘‘substitution’ というメッセージを表示する例外が発生します。
詳細については、wt.util.resource パッケージ (特に wt.util.resource.WTListResourceBundle) の Javadoc を参照してください。
モデルに関する参考情報
すべての (サポートされている) クラスに関する参考情報が Javadoc に含まれており、すべての (サポートされている) GenAs_ アノテーション付きクラスの Javadoc に GenAs アノテーションが含まれています。つまり、Windchill のスキーマに関するすべての参考情報が Javadoc に含まれており、独自のクラスをモデル化するときに参照できます。さらに、アノテーションそのものも Javadoc に含まれています (com.ptc.windchill.annotations.metadata パッケージ内にあります)。アノテーションに関する情報と使用例は、Javadoc ですぐに参照できます。
Javadoc は、モデル化の方法を理解するため、および Windchill のモデルを例として検索するためのとりわけ便利です。ただし、特定のクラスが一部を成す関連付けを Javadoc だけで特定することは困難です。通常、役割メンバーの Javadoc には、その関連付けへの参照が含まれていないからです。特定のオブジェクトが一部を成す関連付けに関する情報は、Windchill のイントロスペクションを介して入手でき、2 つのユーティリティを介してアクセスできます。
1 つ目のユーティリティは、InfoReport です。windchill シェルでクラスを指定して InfoReport を実行すると、そのクラスに関するあらゆる既知のデータが表示されます。これには、関連付けをはじめ、プロパティ、データベース情報、子孫が含まれます。
2 つ目のユーティリティは、Windchill ユーザーインタフェースの一部として用意されていますが、デフォルトでは有効になっていません。有効にすると、クライアントによって、イントロスペクション情報をブラウズするためのナビゲーション可能なインタフェースが提供されます。
これを有効にするには、次の手順にしたがいます。
1. 「サイト」> 「ユーティリティ」> 「プリファレンスマネージャ」の順に移動します。
2. 「ツリーを検索」を使用して、「Client Customization」を見つけます。
3. それを右クリックし、「プリファレンスを設定」を選択して、値を「はい」に設定します。
4. ブラウザを再表示します。
5. 「ツール」アイコン (「サイト」の横にある) を参照します。
6. 「ツール」を選択し、「Modeled Objects」を選択します。
Eclipse による開発
この章の例 (およびそれに類似するカスタマイズ) は、テキストエディタ (記述用) と Ant (構築用) だけで開発できますが、IDE である Eclipse (http://eclipse.org) を使用して開発することもできます (tools.xmleclipse_project.help ターゲットをベースとして使用できます)。
具体的には、Eclipse をインストールし、FileSync プラグインをインストールしてから、ワークスペースとプロジェクトを生成し (eclipse_project target を介して)、ワークスペースとプロジェクトの両方を使用するように Eclipse を設定する必要があります。これについては、eclipse_project.help で説明します。
生成された Eclipse プロジェクトは、tools.xml とまったく同じように、<ロードポイント>/src 内のソースを使用するように設定されています。これは、Eclipse が管理する出力ディレクトリ (<ロードポイント>/eclipse_codebase) に構築され、FileSync を使用して "実際の" codebase (<ロードポイント>/codebase) への変更を適用します。これにより、クラスターゲットを呼び出すことと最終的には同じ結果が得られます。生成されたプロジェクトは、直接 <ロードポイント>/codebase にコンパイルされません。このディレクトリにコンパイルされると、Eclipse がそれを消去するからです。
Eclipse では、コンパイルとアノテーション処理がサポートされています。ソースファイルは、保存されるたびに、ただちにコンパイルされます。コンパイルでは、必要に応じて、アノテーションプロセッサが呼び出され、コードが生成されます。Eclipse では、rbInfo ファイルの構築と SQL の生成まではサポートされていませんが、これらのコンポーネントを構築するためには、引き続き tools.xml を使用する必要があります。
Eclipse ユーザーは、従来の rbInfo によってフォーマットされた StringResourceInfo バンドルの代わりに WTListResourceBundle とそのアノテーションを使用できます。ResourceInfo.class=wt.tools.resource.StringResourceInfo タイプの rbInfo ファイルは、Java クラスファイルにコンパイルできる唯一の rbInfo フォーマットです。Eclipse では、このように生成されたクラスファイルは認識されないため、コンパイルは行われません (このようなバンドルで定数が使用されていることがエラーとして報告されます)。対照的に、WTListResourceBundle は Eclipse によって正常にコンパイルされ、正常に認識されます。既存 StringResourceInfo ファイルがある場合は、bundle_convert ターゲットを使用してこれらのファイルを変換することを検討してください。
生成された Eclipse ワークスペースには、MethodServer をデバッグするためのデバッグコンフィギュレーションが含まれています (詳細については、ヘルプを参照してください)。Windchill にはソースは用意されていませんが、ユーザーは独自のコードをデバッグできます。
eclipse_target には、とりわけ、ほとんどオプションが残されていません。これは、正常に機能するワークスペースまたはプロジェクトが確実に作成されるようにするための意図的な制限です。eclipse_project に関連する tools.xml のターゲットと eclipse_project そのものの出力をおおまかに確認するだけで、どのような処理が行われているかをだいたい把握でき、どのように結果をカスタマイズすればニーズに適合するかを判断できます。
モデル化されたカスタマイズの公開
このセクションでは、モデル化されたカスタマイズを公開する際のガイドランについて説明します。ここでの "公開" とは、あるシステムから別のシステム (ソースからターゲットなど) にカスタマイズをコピーすることを指します。使用するプロセスは、カスタマイズの実際のソースとターゲットによって異なります。
モデル化されたカスタマイズが構築されると、以下の 3 つの領域でインストールに影響が及びます。
1. 1. <loadpoint>/codebase にある次のファイル内のモデル化された (アノテーション付き) クラスの登録:
modelRegistry.properties
associationRegistry.properties
descendentRegistry.properties
2. コンパイル済みファイルと生成されたファイルの追加:
Java クラス (*.class)
イントロスペクション成果物ファイル (*.ClassInfo.ser)
シリアライズされたバンドルファイル (*.RB.ser)
3. <loadpoint>/db 内のデータベーススクリプトの更新による追加のスキーマ (インデックスを含む) の組み込み
データベースファイル (*.sql)
さらに、たとえばサービスを登録するために site.xconf にエントリが追加されている可能性があります。
どちらのアプローチでも、以下の操作を行う必要があります。
1. カスタマイズによって加えられた変更 (上記のファイル) を送信先システムにコピーします。
2. テーブルとインデックスを作成するために必要な SQL スクリプトを呼び出すことによって、スキーマをインストールします。
3. 送信先システムの site.xconf を補足して、カスタマイズの変更を組み込みます (および xconfmanager を実行します)。
4. 送信先システムを再起動します。
開発システムから本番システムへのモデル化されたカスタマイズの公開
一般的なシナリオの 1 つとして、ソースが開発システムでターゲットが本番システムである環境があります。このシナリオでは、公開プロセスを簡略化する前提を設けることができます。最も重要な点として、開発システムと本番システムは基本的にクローンであることを前提としています。
このセクションでは、カスタマイズが開発されるソースを "開発システム" と呼びます。"本番システム" とは、顧客が現在その生産業務に使用している送信先システムか、新規の公開、マイグレーション、アップグレードの一環として開発されている新しい本番システムを指します。環境によっては、テストシステムやステージング (運用前) システムなど、保守が必要なその他のシステムも含まれることがあります。以下で説明する、カスタマイズを本番システムに公開するためのステップはすべて、同じ前提に当てはまるかぎり、その他のシステムにも適用されます。
このシナリオでは、開発システムと本番システムはクローンであり、開発システムに対して変更を加える際に、これらの変更を本番システムにコピーできることを前提としています。このため、本番システムと開発システムが同じ基本状態を共有している (同じ製品がインストールされ、同じパッチであり、同じリリースレベルである) ことが重要です。そうでなければ、クラスに互換性がなかったり、レジストリファイルに不要なエントリが含まれていたり (または重要なエントリがなかったり)、データベーススキーマが不適切であったりします。
これらの前提に当てはまる場合、以降のステップのガイドラインに従うことができます。
1. カスタマイズによって加えられた変更 (上記のファイル) を本番システムにコピーします。
2. カスタマイズによって加えられた変更を本番システムにコピーします。
a. C:\temp\original_registry_files のカスタマイズを開始する前に、次のレジストリファイルをコピーします。
associationRegistry.properties
descendentRegistry.properties
modelRegistry.properties
moduleRegistry.properties
b. モデリングされた新しいオブジェクトを作成します。詳細については、新しいドキュメントサブクラスのモデル化を参照してください。
c. d:\Windchill\temp\_model_registry の内部に追加または削除する結合ファイルを作成するには、Windchill シェルで次のコマンドを実行します。
ant -f bin/tools.xml registry_diff -Dregistry_diff.basedir=C:\temp\original_registry_files -Dregistry_diff.modsdir=D:\windchill\codebase -Dregistry_diff.diffdir=d:\Windchill\temp\_model_registry
d. _model_registry フォルダを新しい Windchill ターゲットシステムにコピーして d:\Windchill\temp に貼り付けます。
e. 新しいターゲットシステムの Windchill シェルで次のコマンドを実行します。
ant -f bin/tools.xml registry_merge -Dregistry_merge.adds=D:\Windchill\temp\_model_registry\reg_adds -Dregistry_merge.removes=D:\Windchill\temp\_model_registry\reg_removes
3. テーブルとインデックスを作成するために必要な SQL スクリプトを呼び出すことによって、スキーマをインストールします。
4. 本番システムの site.xconf を補足して、カスタマイズの変更を組み込みます (および xconfmanager を実行します)。
5. 本番システムを再起動します。
別のアプローチによるモデル化されたカスタマイズの公開
ソースからターゲットにカスタマイズを公開するには、ソース環境で行った操作を送信先システムでも実行する必要があります。1 つのアプローチとして、単純にソースをコピーし、送信先システムで再構築する方法があります。ただし、このアプローチでは送信先システムでのコンパイルが必要となりますが、送信先システムが本番システムである場合、コンパイルはおそらく許可されません。
もう 1 つのアプローチとして、Git や Subversion などのバージョン制御システムを使用する方法があります。このアプローチでは、ロードポイント全体をバージョン制御の対象にして、バージョン制御システムによってカスタマイズによるインストールへの影響をユーザーに通知し、変更内容をマージします。
モデル化されたカスタマイズのマージ
送信先システムに、公開するソースシステムにないカスタマイズが含まれている場合、送信先システム内のレジストリファイルにマージ可能な差分レジストリファイルを作成する必要があります。registry_diff ターゲットをソースシステムファイルに対して実行することで、registry_merge ターゲットを使用して送信先システムにマージする差分ファイルを生成できます。
registry_diff ターゲットは、以下で説明する必要なフォルダへのアクセス権があるかぎり、いずれかのシステムの Windchill シェルから実行できます。
ant -f <loadpoint>/bin/tools.xml registry_diff -Dregistry_diff.basedir=/wt_dev/base
-Dregistry_diff.modsdir=/wt_dev/codebase -Dregistry_diff.diffdir=/wt_dev/diff
registry_diff.basedir - カスタマイズを開発する前の、オリジナルのレジストリファイルが含まれているフォルダ。
カスタマイズを行う前のレジストリファイルの元の状態を維持しておくのが理想的です。そうでない場合、オリジナルのレジストリファイルにアクセスするためには、カスタマイズしたクラスを登録解除し、レジストリファイルをベースとして残してから、カスタマイズを再構築する必要があります。たとえば、プレフィックス "ext." で始まるカスタマイズしたクラスを登録解除するには、次の操作を行います。
"ext." で始まるか "=ext." を含む行を除去します。
ant -f <loadpoint>/bin/tools.xml model_uninstall
-Dmodel_uninstall.filter="\Aext\.|=ext\."
注記: "ext." で始まるすべてのキーと値がこれに合致します。
その他の使用例を表示するには、ant -f <loadpoint>/bin/tools.xml model_uninstall.help を実行します。
registry_diff.modsdir は開発レジストリファイル (開発コードベース) が含まれているフォルダです。これはカスタマイズが登録されているバージョンのレジストリファイルです。
registry_diff.diffdirbasedirmodsdir の間の差分が出力されるフォルダです。このディレクトリ内に reg_addsreg_removes の 2 つのフォルダが作成されます。この 2 つのフォルダは、以下で説明するように、送信先システムに対する registry_merge コマンドによって使用されます。
registry_merge ターゲットは送信先システムの Windchill シェルから実行する必要があり、registry_diff ターゲットによって生成されたファイルにアクセス可能である必要があります。
ant -f <loadpoint>/bin/tools.xml registry_merge
-Dregistry_merge.adds=/wt_dev/diff/reg_adds
-Dregistry_merge.removes=/wt_dev/diff/reg_removes
registry_merge.adds は、送信先システムに追加されるカスタマイズエントリを含むフォルダです。
registry_merge.removes は、送信先システムから除去されるカスタマイズエントリを含む (オプションの) フォルダです。