JCSP を使って書いたチャットのコード(2)

既に忘れかけてたけど-_-、一応 jcsp.awt を用いたバージョン。
まぁ、ここは日記の使い勝手検証目的みたいなもんだし^^;。

jcsp.awt はテキスト入出力時のフォーカス制御などに柔軟性が無いなど、まともなアプリケーションにしようと思ったら苦労することが多くありそう。
統一的なインターフェイスと並列化による即応性は魅力なんですけどねぇ…。

[ActiveChat.java]


import java.awt.*;
import jcsp.awt.*;
import jcsp.lang.*;
import jcsp.plugNplay.*;
import jcsp.util.*;

class ActiveChat {
public static void main(String[] args) throws Exception {
Any2OneChannel sendSocket =
Any2OneChannel.create(new OverWriteOldestBuffer(10));

CSProcess[] nodes = new CSProcess[5];
Channel[] readSockets =
One2OneChannel.create(
nodes.length - 1,
new OverWriteOldestBuffer(10));

for (int i = 0; i < nodes.length - 1; i++) {
nodes[i] = new ChatWindow("node:"+i, readSockets[i], sendSocket);
}
AltingChannelInput receiverAdder =
One2OneChannel.create(new OverWriteOldestBuffer(1));
nodes[nodes.length - 1] =
new DynamicDelta(sendSocket, receiverAdder, readSockets);

new Parallel(nodes).run();
}
}

class ChatWindow implements CSProcess {
private String name;
private ChannelInput in;
private ChannelOutput out;

ActiveClosingFrame frame;
ActiveTextArea view;
ActiveTextEnterField input;
Filter filter;

public ChatWindow(String name, ChannelInput in, ChannelOutput out) {
this.name = name;
this.in = in;
this.out = out;

filter = new Filter(out) {
protected Object filter(Object o) {
if (((String)o).length() == 0) return null;
input.getActiveTextField().setText("");
return o + "\n";
}
};

frame = new ActiveClosingFrame("Example");

view = new ActiveTextArea(in, null, "", 20, 60);
view.setEditable(false);
input = new ActiveTextEnterField(null, filter.out(), "");

Panel p = new Panel(new BorderLayout());
p.add(view, BorderLayout.CENTER);
p.add(input.getActiveTextField(), BorderLayout.SOUTH);

final Frame realFrame = frame.getActiveFrame();
realFrame.setBackground(Color.green);
realFrame.add(p);
realFrame.pack();
realFrame.setVisible(true);
}

public void run() {
new Parallel(
new CSProcess[] {
frame,
view,
input,
filter
}
).run();
}
}

/**
* write に filter を付加する。
* 利用者はオリジナルの代わりに Filter#out() で得た ChannelOutput を用いる。
*/
abstract class Filter implements CSProcess {
private Channel in;
private ChannelOutput out;

protected Filter(ChannelOutput out) {
this.out = out;
in = One2OneChannel.create(new OverWriteOldestBuffer(10));
}

public final ChannelOutput out() {
return in;
}

public final void run() {
Object o;
while (true) {
o = filter(in.read());
if (o != null) out.write(o);
}
}

/** null を返すことで送信を拒否することもできる。 */
protected abstract Object filter(Object o);
}