Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

コマンド ライン API を使用した要件リンクの更新または修復

この例では、1 つ以上のアーティファクトの移動または名前変更後に、設計アーティファクトと要件の間のリンクが古くなるという一般的な状況について説明しています。切断されたリンクを削除して新しいリンクを作成するのではなく、作成/変更の履歴とその他のプロパティ (説明、キーワード、コメントなど) が保持されるように既存のリンクを更新する必要があります。以下の API の使用が示されます。

  • Requirements Toolbox™ のエントリとリンクを見つけるためのslreq.find

  • 特定の ReqSet 内で目的のエントリを見つけるためのfind

  • LinkSet 内のすべての外向きリンクをクエリするためのgetLinks

  • リンク元に関する簡単な情報を求めるsource

  • リンク先に関する簡単な情報を求めるdestination

  • "格納対象としての" ターゲット情報を得るためのslreq.Link("解決対象" に関する Link.destination() とは異なる)

  • ターゲット ドキュメントが移動されたときにリンク先を更新するためのslreq.LinkSet

  • ソース ドキュメントが移動されたときに以前にインポートしたセットを更新するためのslreq.ReqSet

  • 更新済みのドキュメントから以前にインポートした参照を更新するためのupdateFromDocument

  • 既存の "直接リンク" を "参照リンク" に変換するためのslreq.LinkSet

  • 指定された slreq.Link のリンク元またはリンク先いずれかの終端を表示するために使用されるslreq.show

一部の場所では、リタイア済みの SLVnV 製品の要件管理インターフェイス (RMI) の部分から継承した従来のrmiAPI も使用します。

プロジェクト ファイル例

始める前に、slreq.clearコマンドを実行して必ずクリーンな初期状態にしてください。次に、「slreqCCProjectStart」と入力してクルーズ コントロール プロジェクトの例を開きます。これにより、リンクされたアーティファクト ファイルのコレクションが MATLAB/Projects フォルダーの下の新しいサブフォルダーに解凍されます。

slreq.clear();
slreqCCProjectStart();

要件にリンクされた Simulink モデル

プロジェクトの依存関係グラフのごく一部に焦点を当てます。外部の Microsoft® Word ドキュメント crs_reqs.docx へのリンクを数個もつ crs_plant.slx Simulink® モデルを開きます。

open_system('crs_plant');

いずれかのリンクで移動して、リンクされたドキュメントを開きます。

rmi('view', 'crs_plant/status', 1);

Word ドキュメントの対応するセクションが開きます。

コマンド ライン API の使用方法と、crs_plant.slx から crs_reqs.docx へのリンクのチェック方法を以下に示します。

linkSet = slreq.find('type', 'LinkSet', 'Name', 'crs_plant');
links = linkSet.getLinks();
disp('Original Links to Word document:');
Original Links to Word document:
for i = 1:numel(links)
    linkTarget = links(i).getReferenceInfo();
    if contains(linkTarget.artifact, 'crs_req.docx')
        source = links(i).source;
        disp(['    found link from ' strrep(getfullname([bdroot source.id]),newline,'') ...
            ' to crs_req.docx']);
    end
end
    found link from crs_plant/Vehicle1/vehiclespeed to crs_req.docx
    found link from crs_plant/throttDrv to crs_req.docx
    found link from crs_plant/status to crs_req.docx
    found link from crs_plant/throttleCC to crs_req.docx

インポートされた参照が存在する場合の直接リンクの移動

MATLAB® コマンド ラインで、「slreq.editor」と入力して、"要件エディター" を開きます。読み込まれた 2 つの要件セット crs_req.slreqxcrs_req_func_spec.slreqx が表示されます。最初の要件セットは crs_req.docx からインポートされた参照のコレクションであり、2 番目の要件セットは "要件エディター" で手動により作成されました。Word ドキュメントを閉じて、crs_plant/status Inport ブロックからの同じリンクで移動した場合、インポートされた読み込み済みの要件セットの中で一致する参照が移動アクションによって検出されるため、対応するインポート済みの参照が "要件エディター" で強調表示されます。

この場合でも、[ドキュメントに表示] ボタンを使用して、リンクされた要件を元のドキュメントのコンテキストで表示することができます。

slreq.editor();
rmidotnet.MSWord.application('kill');
rmi('view', 'crs_plant/status', 1);

使用例 1: ドキュメントの名前変更後のリンクのバッチ更新

crs_req_v2.docx という名前の更新済みバージョンの要件ドキュメントが受信されるとします。ここで、更新済みドキュメントの対応するセクションを対象にするために、crs_plant.slx 内にリンクが必要です。この例では、元のドキュメントのコピーを同じフォルダー内に作成し、変更済みの名前を付けます。次に、slreq.LinkSetAPI を使用して特定の LinkSet 内のすべてのリンクをバッチ更新し、ドキュメントの新しいコピーに接続します。

copyfile(fullfile(pwd, 'documents/crs_req.docx'), fullfile(pwd, 'documents/crs_req_v2.docx'));
linkSet.updateDocUri('crs_req.docx', 'crs_req_v2.docx');

一致するリンクの更新の検証

同じリンクで移動し、適切なバージョンの外部ドキュメントが開くことを確認できます。前と同じようにすべてのリンクを反復すると、4 つすべてのリンクが意図したとおりに更新されたことが確認されます。

rmi('view', 'crs_plant/status', 1); % updated document opens
links = linkSet.getLinks();
disp('Links to Word document after update:');
Links to Word document after update:
for i = 1:numel(links)
    source = links(i).source;
    linkTarget = links(i).getReferenceInfo();
    if contains(linkTarget.artifact, 'crs_req.docx')
        warning(['link from ' source.id ' still points to crs_req.docx']);  % should not happen
    elseif contains(linkTarget.artifact, 'crs_req_v2.docx')
        disp(['    found link from ' strrep(getfullname([bdroot source.id]),newline,' ')...
            ' to crs_req_v2.docx']);
    end
end
    found link from crs_plant/Vehicle1/vehicle speed to crs_req_v2.docx
    found link from crs_plant/throttDrv to crs_req_v2.docx
    found link from crs_plant/status to crs_req_v2.docx
    found link from crs_plant/throttleCC to crs_req_v2.docx

リンクの更新後にインポートされた参照へ移動

上で示したように、インポートされた参照を "要件エディター" で利用できる場合、リンクの移動によって一致する参照オブジェクトが選択されます。ただし、ドキュメント crs_req_v2.docx の新しいバージョンのリンクを更新したばかりであり、このドキュメントに関してインポートされた参照はありません。"要件エディター" が存在している場合に Simulink ブロックから移動すると、外部の Word ドキュメントに直接移動します。

こうした不整合を回避するには、更新されたドキュメント名との関連付けを維持するために、以前にインポートされた参照を更新する必要があります。slreq.ReqSetAPI を使用してこのタスクを達成します。さらに、更新されたドキュメントには変更済みの要件がある場合があるため、updateFromDocument API を使用して Requirements Toolbox 側に保存されている参照項目の更新を取り込まなければなりません。これが完了したら、Simulink モデルからの移動によって、一致する、インポートされた参照が特定されます。

インポートされた参照をもつ要件セットを見つけます。ソース ファイルの場所を更新し、最上位のインポート ノードを見つけます。

reqSet = slreq.find('type', 'ReqSet', 'Name', 'crs_req');
reqSet.updateSrcFileLocation('crs_req.docx', 'crs_req_v2.docx'); 
importNode = reqSet.find('CustomId', 'crs_req_v2');

インポートされた参照を、ソース ファイルから更新します。Microsoft Word を閉じます。次に、"要件エディター" 内の更新された参照に移動します。

importNode.updateFromDocument();
rmidotnet.MSWord.application('kill');
rmi('view', 'crs_plant/status', 1);

使用例 1 の後のクリーンアップ

プロジェクトを閉じるときにプロンプトが表示されるのを防ぐため、リンク データを破棄します。プロジェクトを閉じます (MATLAB パスの変更もクリーンアップされます)。Microsoft Word を閉じます。

slreq.clear();                        
prj = simulinkproject(); prj.close();
rmidotnet.MSWord.application('kill'); 

使用例 2: インポートされた参照に完全に依存するようにリンクをバッチ更新

上記の使用例 1 で示したように、ドキュメントの移動や名前変更が行われた場合は、外部ドキュメントへの "直接リンク" を維持するためにさらなる作業が必要です。より適切なワークフローは、既存の "直接リンク" を "参照リンク" に変換することです。参照リンクとは、*.slreqx ファイル内のインポートされた References を指し、元のドキュメントの場所または名前に関する情報を複製しないリンクのことです。このオプションを使用する場合、外部のソース ドキュメントとの関連付けはインポートされた参照をホストする要件セットにのみ保存されます。

このワークフローを示すために、新しいサブフォルダー内でクルーズ コントロール モデルの要件定義を再度開くことで同じ初期点から再開します。Simulink モデルを自分のディレクトリにコピーし、開きます。

slreqCCProjectStart();
copyfile(fullfile(pwd, 'documents/crs_req.docx'), fullfile(pwd, 'documents/crs_req_v2.docx'));
open_system('crs_plant');

インポートされた参照をもつ crs_plant リンク セットおよび crs_req 要件セットを見つけます。

linkSet = slreq.find('type', 'LinkSet', 'Name', 'crs_plant');
reqSet = slreq.find('type', 'ReqSet', 'Name', 'crs_req');

その後、slreq.LinkSetAPI を使用して crs_plant.slmx 内のすべての直接リンクを更新します。次に、リンク セット内にすべてのリンクの配列を作成します。

linkSet.redirectLinksToImportedReqs(reqSet);
links = linkSet.getLinks();

このような方法で LinkSet を更新した後、すべてのリンクをループして crs_req.docx ファイルへの "直接" リンクが存在しないことを確認します。

disp('Check for links to original external document:');
Check for links to original external document:
counter = 0;
for i = 1:numel(links)
    linkTarget = links(i).getReferenceInfo();
    if contains(linkTarget.artifact, 'crs_req.docx')
        source = links(i).source;
        warning(['link from ' source.id ' still points to crs_req.docx']);
        counter = counter + 1;
    end
end
disp(['    Total ' num2str(counter) ' links to external document']);
    Total 0 links to external document

Simulink モデルから更新済みの参照に移動します。

rmi('view', 'crs_plant/status', 1);

参照へのリンクと外部ドキュメントの名前変更

すべてのリンクが外部ドキュメントではなくインポートされた参照を指している場合、インポート ノードが新しい外部ドキュメント名で更新されている限り、トレーサビリティ データの整合性はドキュメントの名前変更後も維持されます。使用例 1 のように、Word ドキュメントを新しい名前で再保存することで、更新バージョンの外部要件ドキュメントが存在するように見せかけます。その後、以前と同じ API を使用して、インポート ノードに必要な更新を実行します。ここで、リンクはインポートされた参照に依存しており、インポートされたドキュメントに関する情報を保存しないため、使用例 1 のすべての手順を実行した後のように、Simulink モデルからの移動によって、更新された参照に移動できます。

現在、参照は更新された外部ドキュメントに関連付けられています。[ドキュメントに表示] ボタンは更新された (名前が変更された) ドキュメントを開きます。LinkSet 側ではこれ以上の調整は必要ありません。

インポートされた参照をもつ要件セットを見つけます。ソース ファイルの場所を更新し、最上位のインポート ノードを見つけます。

reqSet = slreq.find('type', 'ReqSet', 'Name', 'crs_req');
reqSet.updateSrcFileLocation('crs_req.docx', 'crs_req_v2.docx'); 
importNode = reqSet.find('CustomId', 'crs_req_v2');

インポートされた参照を、ソース ファイルから更新します。次に、"要件エディター" 内の更新された参照に移動します。

importNode.updateFromDocument();
rmi('view', 'crs_plant/status', 1);

使用例 2 の後のクリーンアップ

プロジェクトを閉じるときにプロンプトが表示されるのを防ぐため、リンク データを破棄します。プロジェクトを閉じます (MATLAB パスの変更もクリーンアップされます)。Microsoft Word を閉じます。

slreq.clear();                        
prj = simulinkproject(); prj.close();
rmidotnet.MSWord.application('kill'); 

使用例 3: リンクされたアーティファクトを新しいプロジェクトに移動

ここでは、リンクされたアーティファクトをもつ既存のプロジェクトを分岐していて、元のプロジェクトと同じようにすべてのトレーサビリティ リンクをもつ名前変更された新しい一連のアーティファクトを作成する必要があると仮定します。前と同じように、クルーズ コントロール プロジェクトをクルーズ コントロール モデルの要件定義から新しいサブフォルダーに抽出し、上記の使用例 2 で行ったように "直接リンク" を "参照リンク" に変換します。先に進み、それぞれを _v2. という名前で再保存することで、リンクされたアーティファクトの "新バージョン" を作成します。

名前を変更した Simulink モデルのコピー、インポートされた外部ドキュメント、およびインポートされた要件を含む要件セットの作成後、問題が 1 つあります。つまり、名前を変更したモデルが、名前を変更した要件セットではなく元の要件セットに含まれる参照にリンクされているということです。元のモデルが読み込まれていないため、[詳細] ペインの [リンク] にはリンクが未解決と表示されます。

クルーズ コントロール プロジェクトを開き、crs_plant モデルを開きます。crs_plant のリンク セットと、要件セット crs_req を見つけます。

slreqCCProjectStart();
open_system('models/crs_plant.slx');
linkSet = slreq.find('type', 'LinkSet', 'Name', 'crs_plant');
reqSet = slreq.find('type', 'ReqSet', 'Name', 'crs_req');

直接リンクを参照リンクに変換します。ファイルの名前を変更したコピーを作成し、保存します。

linkSet.redirectLinksToImportedReqs(reqSet);     
mkdir(fullfile(pwd, 'copied'));
save_system('crs_plant', fullfile(pwd, 'copied/crs_plant_v2.slx'));  
reqSet.save(fullfile(pwd, 'copied/crs_req_v2.slreqx'));              
copyfile('documents/crs_req.docx', 'copied/crs_req_v2.docx');        

名前を変更した要件セットを、名前を変更したドキュメントに関連付けます。最上位のインポート ノードを見つけます。

reqSet.updateSrcFileLocation('crs_req.docx', fullfile(pwd, 'copied/crs_req_v2.docx'));
importNode = reqSet.find('CustomId', 'crs_req_v2');

インポートされた参照を更新することにより、名前を変更した要件セットの内容が、名前を変更したドキュメントの内容に一致することを確認します。名前を変更した Simulink モデルから、名前を変更した要件セットの項目に移動します。元の要件セット内の古い項目が強調表示されます。これは正しくありません。

importNode.updateFromDocument();
rmi('view', 'crs_plant_v2/status', 1);

名前を変更したリンク元のリンクを更新して、名前を変更したリンク先をターゲットとして使用する

使用例 1 と同じように、LinkSet.updateDocUri(OLD, NEW) API を使用して crs_plant_v2.slmx のリンクを更新し、元の crs_req.slreqx ではなく名前が変更された要件セット crs_req_v2.slreqx をリンク ターゲットとして使用することができます。これが完了したら、名前を変更したモデル内のブロックから再度移動します。名前が変更された要件セット中の要件が選択され、[詳細] ペインの [リンク] (右下) のリンクは解決されます。

モデルの新しいコピーである crs_plant_v2 のリンク セットを見つけます。モデルの新しいコピーとリンクされた要件セットの名前を更新します。名前を変更した Simulink モデルから、名前を変更した要件セットの項目に移動します。今回は、正しい項目が強調表示されます。

linkSet = slreq.find('type', 'LinkSet', 'Name', 'crs_plant_v2');
linkSet.updateDocUri('crs_req.slreqx', 'crs_req_v2.slreqx');
rmi('view', 'crs_plant_v2/status', 1);

使用例 3 の後のクリーンアップ

開いている要件セットとリンク セットをクリアし、開いているモデルとプロジェクトを変更を保存せずに閉じます。Microsoft Word を閉じます。

slreq.clear();                        
bdclose('all');     
prj = simulinkproject(); prj.close(); 
rmidotnet.MSWord.application('kill');