例題04c ベースプロセス間のオブジェクト受け渡し

(1)概要

エージェントが持つベースプロセス間でオブジェクトを受け渡す方法を示す。
(注意:ネームサーバNameServer.jarの起動が必要。)

(2)エージェント

エージェント名ファイル名説明
ClipSenderClipSender.dashオブジェクトを渡すエージェント
ClipSender.class
ベースプロセス
ClipReceiverClipReceiver.dashオブジェクトをもらうエージェント
ClipReceiver.class
ベースプロセス
なしMyClass.class受け渡される自作オブジェクト

(2.1)ClipSender

●知識記述ファイル (ClipSender.dash)
(agent ClipSender
 
 (property
  (create :author "taka")
 )
 
 (initial_facts
 )
 
 (knowledge
    (rule startup
      (Msg :performative __INIT_I)
      (Status :name ?name)
      -->
      (inspect nonstop)
      (loadBP baseProcess.dashSample.ClipSender)  // BP読み込み
      (startBP)                         // run()呼び出し
      (bind ?t (current-time))
      (make (key :name ?name :time ?t))
    )
    
    //キーを用いた自作オブジェクトの格納
    (rule putmyclass
      (key :name ?name :time ?t) = ?arg
      -->
      (bind ?key (toString ?arg))
      //キーを用いて、DVM内クリップボードに
      //自作オブジェクトを格納
      (control putMyClass(?key))
    )

    //キー要求を受け取り、キーを送る
    (rule receive-keyRequest
      (Msg :performative keyRequest :from ?sender ) = ?msg
      (key :name ?name :time ?t) = ?arg
      -->
      (bind ?key (toString ?arg))
      (send :performative sendKey :to ?sender :content (?key))
      (remove ?msg)
    )
  )
)

●ベースプロセス (ClipSender.java)
package baseProcess.dashSample;

import dash.*;

/**
 * ClipSender
 */
public class ClipSender implements DashBP {

	private DashAgent agent;

	/** コンストラクタ。アクション(loadBP)実行時に呼ばれる。 */
	public ClipSender() {
	}

	/** アクション(loadBP)実行時に呼ばれる。*/
	public void setAgent(DashAgent agent) {
		this.agent = agent;
	}

	/** アクション(startBP)実行時に呼ばれる */
	public void run() {
	}

	/** エージェントの終了時に呼ばれる */
	public void finalizeBP() {
	}

	//自作オブジェクトの格納
	public void putMyClass(Object[] str) {
		String key = (String) str[0];
		MyClass mc = new MyClass();
		//DVM(Dash Virtual Machine)内のクリップボードに
		//自作オブジェクトを格納
		agent.cm.putSerialized(key, mc);
	}
}

(2.2)ClipReceiver

●知識記述ファイル (ClipReceiver.dash)
(agent ClipReceiver
 
 (property
  (create :author "taka")
 )
 
 (initial_facts
 )
 
 (knowledge
    (rule startup
      (Msg :performative __INIT_I)
      (Status :name ?name)
      -->
      (inspect nonstop)
      (loadBP baseProcess.dashSample.ClipReceiver)  // BP読み込み
      (startBP)                          // run()呼び出し
      (control startup ())
    )

    // ベースプロセスからのイベントを受け取り、
    // ClipSenderにキーを要求する
    (rule event-handling
      (Msg :performative __Event :content (?string)) = ?msg
      -->
      (bind ?agents (lookup :rname ClipSender))
      (bind ?agent (shift ?agents))
      (send :performative keyRequest :to ?agent:name :content ())
      (remove ?msg)
     )
    
    // ClipSenderから、キーを受け取る
    (rule receive-sendKey
     (Msg :performative sendKey :from ?sender :content (?key)) = ?msg
     -->
     //キーを用いて、DVM内のクリップボードから自作オブジェクトを取り出す
     (control getMyClass (?key))
     (remove ?msg)
    )
  )
)

●ベースプロセス (ClipReceiver.java)
package baseProcess.dashSample;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import dash.*;
import java.io.*;

public class ClipReceiver extends JFrame implements DashBP, ActionListener {

	private DashAgent agent;

	JTextArea textarea;
	JButton startbutton;
	JButton stopbutton;

	/** コンストラクタ。アクション(loadBP)実行時に呼ばれる。 */
	public ClipReceiver() {
		super("ClipReceiver");
	}

	/** アクション(loadBP)実行時に呼ばれる。*/
	public void setAgent(DashAgent agent) {
		this.agent = agent;
	}

	/** アクション(startBP)実行時に呼ばれる
	 *
	 * */
	public void run() {
	}

	//キーを用いて自作オブジェクトを取り出す
	public void getMyClass(Object[] str) {
		String key = (String) str[0];
		try {
			//DVM(Dash Virtual Machine)内のクリップボードから
			//自作オブジェクトを取り出す
			ObjectInputStream ois =
				(ObjectInputStream) agent.cm.getObjectInputStream(key);
			MyClass mc = (MyClass) ois.readObject();
			agent.cm.remove(key);
			//取得後の処理
			textarea.append(mc.printDate());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	/** エージェントの終了時に呼ばれる */
	public void finalizeBP() {
		dispose();
	}

	/** startボタンを押し、エージェントにイベントを上げる */
	public void actionPerformed(ActionEvent ae) {
		if (agent != null) {
			if (((JButton) ae.getSource()).getText().equals("Start")) {
				agent.raiseEvent("start");
			} else if (((JButton) ae.getSource()).getText().equals("Finish")) {
				dispose();
			}
		}
	}

	/** ルールstartup内で呼び出される */
	public void startup() {
		setup();
		// ときどきnullなことがある
		while (textarea == null)
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
			}
		textarea.append("起動\n");
	}

	/** ウィンドウを作る */
	private void setup() {
		textarea = new JTextArea(6, 20);
		JScrollPane sc = new JScrollPane(textarea);
		sc.setBorder(new TitledBorder("Input"));

		startbutton = new JButton("Start");
		startbutton.addActionListener(this);

		stopbutton = new JButton("Finish");
		stopbutton.addActionListener(this);

		JPanel panel = new JPanel();
		panel.add(startbutton);
		panel.add(stopbutton);

		GridLayout layout = new GridLayout(1, 2);
		panel.setLayout(layout);

		getContentPane().add(sc, BorderLayout.CENTER);
		getContentPane().add(panel, BorderLayout.SOUTH);

		pack();
		setVisible(true);
	}
}

(2.3)MyClass

●ベースプロセス (MyClass.java)
     1  package baseProcess.dashSample;
     2 
     3  import java.io.Serializable;
     4  import java.util.Calendar;
     5
     6  /**
     7   * 今日の年月日を表示するクラス
     8   */
     9  public class MyClass implements Serializable {
    10    int year;
    11    int month;
    12    int date;
    13
    14    public MyClass() {
    15      Calendar c = Calendar.getInstance();
    16      year = c.get(Calendar.YEAR);
    17      month = c.get(Calendar.MONTH) + 1;
    18      date = c.get(Calendar.DATE);
    19    }
    20
    21    public String printDate() {
    22      return year + "年" + month + "月" + date + "日";
    23    }
    24  }

(3)処理の流れ

��ClipSenderエージェント、ClipReceiverエージェントを起動する

��ClipSenderエージェントは、キーとなるファクトを生成し、そのキーを用いてMyClassオブジェクトのインスタンスをDVM内のクリップボードにシリアライズして格納する( agent.cm.putSerialized(key, myclass) )


��ClipReceiverエージェントは、ベースプロセスから自作オブジェクト取得開始のイベントを受け取ると、ClipSenderエージェントに対しキー要求メッセージを投げ、キーをもらう

��ClipReceiverエージェントは、キーを用いてDVM内のクリップボードからMyClassオブジェクトのインスタンスを取得( ObjectInputStream ois = (ObjectInputStream) agent.cm.getObjectInputStream(key); MyClass mc = (MyClass) ois.readObject() )し、メソッドを実行する


[メモ]
・自作オブジェクトの受け渡しはオブジェクトのコピーが渡されるので、オブジェクトの共有には利用できない。
・自作オブジェクトではなく、標準JDKライブラリ内のオブジェクトobj1は、共有という形で受け渡しを行う。
格納時は agent.cm.put(key, obj1);
取得時は Object1 obj1 = (Object1)agent.cm.get(key);
obj1はベースプロセス間で共有される。