メインコンテンツまでスキップ

シーケンス図のモデルの操作の概要

エクステンションではAPIでシーケンス図の各要素へアクセスすることが可能です。

シーケンス図の要素

No.要素名説明
1ライフラインオブジェクトの生存期間を表すライフラインです。
2メッセージオブジェクト間のメッセージを表します。
3実行仕様オブジェクトが活性化する区間を表します。
4複合フラグメント条件によってメッセージのシーケンスを制御する区間を表します。
5相互作用の利用メッセージのシーケンスの詳細を別のシーケンス図に分割する区間を表します。
6ノートコメントを表します。
制限事項

Next Designのシーケンス図は、他のエディタと同様に表現方法を表すシェイプと表現内容を表すモデルで構成しています。したがって、他のエディタ要素と同様に、シーケンス図の各要素のModelプロパティでモデル情報にアクセスすることができます。ただし、モデルの変更へのビューの追従はサポートしていませんのでご注意ください。シーケンス図のモデル情報でシーケンス図の構成に関わるフィールド値を変更した場合、シーケンス図が開けなくなります。

ライフラインを取得する

ライフラインを取得するにはISequenceDiagramオブジェクトのLifelinesプロパティを用います。

public void GetLifelines(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// ライフラインを取得します
ILifelineShapeCollection lifelines = sequenceDiagram.Lifelines;

var no = 1;
foreach (ILifelineShape lifeline in lifelines)
{
c.App.Output.WriteLine("sample", $"{no}つ目のライフライン : {lifeline.Text}");
no++;
}
}

実行仕様を取得する

ライフラインが持つ実行仕様を取得するにはILifelineShapeオブジェクトのExecutionSpecificationsプロパティを用います。

public void GetExecutionSpecifications(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// 選択されたライフラインが持つ実行仕様を取得します
ILifelineShape lifeline = sequenceDiagram.GetSelectedShapes().FirstOrDefault() as ILifelineShape;
IExecutionSpecificationShapeCollection executionSpecifications = lifeline.ExecutionSpecifications;

c.App.Output.WriteLine("sample", $"ライフライン : {lifeline.Text} が持つ実行仕様は{executionSpecifications.Count()}つ");
}

ISequenceDiagramオブジェクトのExecutionSpecificationsプロパティを用いることで、シーケンス図上のすべての実行仕様を取得することもできます。

public void GetAllExecutionSpecifications(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// 実行仕様を取得します
IExecutionSpecificationShapeCollection executionSpecifications = sequenceDiagram.ExecutionSpecifications;

foreach (IExecutionSpecificationShape executionSpecification in executionSpecifications)
{
// Lifelineプロパティで実行仕様を保持するライフラインにアクセスできます。
ILifelineShape lifeline = executionSpecification.Lifeline;

// Activatorプロパティで実行仕様を活性化するメッセージにアクセスできます。
IMessageShape activator = executionSpecification.Activator;

c.App.Output.WriteLine("sample", $"{lifeline.Text}{activator.Text}により活性化します。");
}
}

メッセージを取得する

ライフラインからの送信・受信メッセージを取得するにはILifelineShapeオブジェクトのExecutionSpecificationsプロパティにアクセスし、実行仕様を取得します。さらに、IExecutionSpecificationShapeオブジェクトのSendMessagesReceiveMessagesプロパティを用いてメッセージを取得します。

public void GetMessages(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// 選択されたライフラインが持つ実行仕様から送信・受信メッセージを取得します
ILifelineShape lifeline = sequenceDiagram.GetSelectedShapes().FirstOrDefault() as ILifelineShape;
var sendMessages = lifeline.ExecutionSpecifications.SelectMany(ec => ec.SendMessages);
var receiveMessages = lifeline.ExecutionSpecifications.SelectMany(ec => ec.ReceiveMessages);

c.App.Output.WriteLine("sample", $"ライフライン : {lifeline.Text} の送信メッセージは{sendMessages.Count()}つ");
c.App.Output.WriteLine("sample", $"ライフライン : {lifeline.Text} の受信メッセージは{receiveMessages.Count()}つ");
}

ISequenceDiagramオブジェクトのMessagesプロパティを用いることで、シーケンス図上のすべてのメッセージを取得することもできます。

public void GetAllMessages(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// メッセージを取得します
IMessageShapeCollection messages = sequenceDiagram.Messages;

foreach (IMessageShape message in messages)
{
// Senderプロパティ、Receiverプロパティで、それぞれ送信元、受信先のライフラインにアクセスできます。
// これらのプロパティは、送信元、受信先がライフラインでない場合は null を返します。
ILifelineShape sender = message.Sender;
ILifelineShape receiver = message.Receiver;
var senderName = sender != null ? sender.Text : "不明";
var receiverName = receiver != null ? receiver.Text : "不明";

c.App.Output.WriteLine("sample", $"{message.Text}は、{senderName}から{receiverName}のメッセージです。");
}
}

IMessageShapeオブジェクトからメッセージのモデルにアクセスすることでメッセージの種類や前後関係を調べることができます。メッセージのモデルは、IMessageShapeオブジェクトのModelプロパティをIMessage型にキャストします。

メッセージの種類を調べる
IMessageオブジェクトのKindプロパティでメッセージの種類を識別できます。

Kindプロパティの値種類
sync同期メッセージ
async非同期メッセージ
create生成メッセージ
destroy破棄メッセージ
reply応答メッセージ

メッセージの前後関係を調べる
IMessageオブジェクトのBeforeプロパティで、先行メッセージ(メッセージと送信元が同じ直前に送信されるメッセージ)を取得できます。また、IMessageオブジェクトのAfterプロパティで、後行メッセージ(メッセージと送信元が同じ直後に送信されるメッセージ)を取得できます。

備考

先行メッセージ、および後行メッセージには応答メッセージは含まれません。また評価対象のメッセージが応答メッセージであった場合は、先行メッセージ、後行メッセージともに null となります。

注意

同一のライフラインから送信するメッセージであっても、実行仕様が異なる送信メッセージは先行メッセージ、後行メッセージとはなりません。

public void GetMessageInfo(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// 選択されたメッセージを取得します
IMessageShape messageShape = sequenceDiagram.GetSelectedShapes().FirstOrDefault() as IMessageShape;
IMessage message = (IMessage)messageShape.Model;

c.App.Output.WriteLine("sample", $"{messageShape.Text}の種類は{message.Kind}です。");

// 先行メッセージ、後行メッセージのシェイプを取得します
IMessageShape beforeMessageShape = GetMessageShape(sequenceDiagram, message.Before);
IMessageShape afterMessageShape = GetMessageShape(sequenceDiagram, message.After);

if (beforeMessageShape != null)
{
c.App.Output.WriteLine("sample", $"{messageShape.Text}の先行メッセージは{beforeMessageShape.Text}です。");
}
if (afterMessageShape != null)
{
c.App.Output.WriteLine("sample", $"{messageShape.Text}の後行メッセージは{afterMessageShape.Text}です。");
}
}

private IMessageShape GetMessageShape(ISequenceDiagram sequenceDiagram, IMessage message)
{
if (message == null) return null;

return sequenceDiagram.Messages.FirstOrDefault(m => m.Model.Equals(message));
}

複合フラグメントを取得する

複合フラグメントを取得するにはISequenceDiagramオブジェクトのFragmentsプロパティを用います。

public void GetFragments(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// 複合フラグメントを取得します
IFragmentShapeCollection fragments = sequenceDiagram.Fragments;

var no = 1;
foreach (IFragmentShape fragment in fragments)
{
c.App.Output.WriteLine("sample", $"{no}つ目の複合フラグメント : {fragment.Text}");
no++;
}
}

IFragmentShapeオブジェクトのOperandsプロパティを用いて、オペランドにアクセスすることもできます。オペランドでは、ガード条件やオペランドの区画内に含まれるメッセージを確認することができます。

public void GetFragmentInfo(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// 選択された複合フラグメントを取得します
IFragmentShape fragment = sequenceDiagram.GetSelectedShapes().FirstOrDefault() as IFragmentShape;

var no = 1;
foreach (IOperandShape operand in fragment.Operands)
{
c.App.Output.WriteLine("sample", $"オペランド[{no}]:{operand.Guard}");

// オペランドの区画内に含まれるメッセージを取得
foreach (IMessageShape message in operand.Messages)
{
c.App.Output.WriteLine("sample", $"-- {message.Text}");
}
no++;
}
}

相互作用の利用を取得する

相互作用の利用を取得するにはISequenceDiagramオブジェクトのInteractionUsesプロパティを用います。

public void GetInteractionUses(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// 相互作用の利用を取得します
IInteractionUseShapeCollection interactionUses = sequenceDiagram.InteractionUses;

var no = 1;
foreach (IInteractionUseShape interactionUse in interactionUses)
{
c.App.Output.WriteLine("sample", $"{no}つ目の相互作用の利用 : {interactionUse.Text}");
no++;
}
}

ノートを取得する

ノートを取得するにはISequenceDiagramオブジェクトのNotesプロパティを用います。

public void GetNotes(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// ノートを取得します
INoteShapeCollection notes = sequenceDiagram.Notes;

var no = 1;
foreach (INoteShape note in notes)
{
c.App.Output.WriteLine("sample", $"{no}つ目のノート : {note.Text}");
no++;
}
}

ISequenceDiagramオブジェクトのNoteAnchorsプロパティで取得できるINoteAnchorShapeを用いることで、シーケンス図の要素に接続されたノートを取得することもできます。

public void GetComments(ICommandContext c, ICommandParams p)
{
ISequenceDiagram sequenceDiagram = c.App.Workspace.CurrentEditor as ISequenceDiagram;
if (sequenceDiagram == null) return;

// 選択されたシーケンス図の要素を取得します
var shape = sequenceDiagram.GetSelectedShapes().OfType<ISequenceShape>().FirstOrDefault();
if (shape == null)
{
return;
}

// ダイアグラムから、要素に接続されたノートアンカを取得します
var anchors = sequenceDiagram.NoteAnchors.Where(a => shape.Equals(a.Target));
foreach (INoteAnchorShape anchor in anchors)
{
INoteShape note = anchor.Note;
c.App.Output.WriteLine("sample", $"コメント: {note.Text}");
}
}