package open.dolphin.impl.claim;
import java.io.*;
import java.net.Socket;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import open.dolphin.client.ClaimMessageEvent;
import open.dolphin.client.ClaimMessageListener;
import open.dolphin.client.ClientContext;
import open.dolphin.client.MainWindow;
import open.dolphin.project.Project;
import org.apache.log4j.Logger;
/**
* SendClaimPlugin
*
* @author Kazushi Minagawa, Digital Globe, Inc.
*/
public class SendClaimImpl implements ClaimMessageListener {
// Socket constants
private final int EOT = 0x04;
private final int ACK = 0x06;
private final int NAK = 0x15;
private final int DEFAULT_TRY_COUNT = 3; // Socket 接続を試みる回数
private final long DEFAULT_SLEEP_TIME = 20*1000L; // Socket 接続が得られなかった場合に次のトライまで待つ時間 msec
private final int MAX_QUEU_SIZE = 10;
// Alert constants
private final int TT_QUEUE_SIZE = 0;
private final int TT_NAK_SIGNAL = 1;
private final int TT_SENDING_TROUBLE = 2;
private final int TT_CONNECTION_REJECT = 3;
// Properties
private String host;
private int port;
private String enc;
private int tryCount = DEFAULT_TRY_COUNT;
private final long sleepTime = DEFAULT_SLEEP_TIME;
private int alertQueueSize = MAX_QUEU_SIZE;
private Thread sendThread;
private final List queue = new LinkedList();
private OrcaSocket orcaSocket;
private MainWindow context;
private String name;
/**
* Creates new ClaimQue
*/
public SendClaimImpl() {
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public MainWindow getContext() {
return context;
}
@Override
public void setContext(MainWindow context) {
this.context = context;
}
private void setup() {
setHost(Project.getString(Project.CLAIM_ADDRESS));
setPort(Project.getInt(Project.CLAIM_PORT));
setEncoding(Project.getString(Project.CLAIM_ENCODING));
if (orcaSocket == null) {
orcaSocket = new OrcaSocket(getHost(), getPort(), sleepTime, tryCount);
}
}
/**
* プログラムを開始する。
*/
@Override
public void start() {
setup();
sendThread = new Thread(new Consumer(orcaSocket));
sendThread.start();
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.INFO, "SendClaim started with = host = {0} port = {1}", new Object[]{getHost(), getPort()});
}
/**
* プログラムを終了する。
*/
@Override
public void stop() {
if (sendThread != null) {
Thread moribund = sendThread;
sendThread = null;
moribund.interrupt();
}
logDump();
}
@Override
public String getHost() {
return host;
}
@Override
public void setHost(String host) {
this.host = host;
}
@Override
public int getPort() {
return port;
}
@Override
public void setPort(int port) {
this.port = port;
}
@Override
public String getEncoding() {
return enc;
}
@Override
public void setEncoding(String enc) {
this.enc = enc;
}
public int getTryCount() {
return tryCount;
}
public void setTryCount(int val) {
tryCount = val;
}
public int getAlertQueueSize() {
return alertQueueSize;
}
public void getAlertQueueSize(int val) {
alertQueueSize = val;
}
/**
* カルテで CLAIM データが生成されるとこの通知を受ける。
* @param e
*/
@Override
public void claimMessageEvent(ClaimMessageEvent e) {
synchronized (queue) {
queue.add(e);
queue.notify();
}
}
/**
* Queue から取り出す。
*/
private Object getCLAIM() throws InterruptedException {
synchronized(queue) {
while (queue.isEmpty()) {
queue.wait();
}
}
return queue.remove(0);
}
public synchronized int getQueueSize() {
return queue.size();
}
/**
* Queue内の CLAIM message をログへ出力する。
*/
public void logDump() {
synchronized(queue) {
Iterator iter = queue.iterator();
while (iter.hasNext()) {
ClaimMessageEvent evt = (ClaimMessageEvent) iter.next();
java.util.logging.Logger.getLogger(this.getClass().getName()).warning(evt.getClaimInsutance());
}
queue.clear();
}
}
private int alertDialog(int code) {
java.util.ResourceBundle bundle = ClientContext.getMyBundle(SendClaimImpl.class);
String proceedString = bundle.getString("optionText.continue");
String dumpString = bundle.getString("optionText.outputLog");
String title = bundle.getString("title.sendClaim");
int option = -1;
StringBuffer buf;
switch(code) {
case TT_QUEUE_SIZE:
buf = new StringBuffer();
buf.append(bundle.getString("messageCompo_0"));
buf.append(getQueueSize());
buf.append(bundle.getString("messageCompo_1")).append("\n");
buf.append(bundle.getString("messageCompo_2")).append("\n");;
buf.append(bundle.getString("messageCompo_3")).append("\n ");
buf.append(bundle.getString("messageCompo_4"));
option = JOptionPane.showOptionDialog(
null,
buf.toString(),
title,
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,null,
new String[]{proceedString, dumpString},proceedString);
break;
case TT_NAK_SIGNAL:
buf = new StringBuffer();
buf.append(bundle.getString("messageCompo_5")).append("\n");
buf.append(bundle.getString("messageCompo_6"));
JOptionPane.showMessageDialog(
null,
buf.toString(),
title,
JOptionPane.ERROR_MESSAGE);
break;
case TT_SENDING_TROUBLE:
buf = new StringBuffer();
buf.append(bundle.getString("messageCompo_7")).append("\n");
buf.append(bundle.getString("messageCompo_8"));
JOptionPane.showMessageDialog(
null,
buf.toString(),
title,
JOptionPane.ERROR_MESSAGE);
break;
case TT_CONNECTION_REJECT:
buf = new StringBuffer();
String fmt = bundle.getString("messageFormat.noResponse");
buf.append(new MessageFormat(fmt).format(new Object[]{host,port})).append("\n");
buf.append(bundle.getString("messageCompo_9")).append("\n");
buf.append(bundle.getString("messageCompo_10")).append("\n");
buf.append(bundle.getString("messageCompo_11")).append("\n ");
buf.append(bundle.getString("messageCompo_12"));
option = JOptionPane.showOptionDialog(
null,
buf.toString(),
title,
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,null,
new String[]{proceedString, dumpString},proceedString);
break;
}
return option;
}
private void warnLog(String result, ClaimMessageEvent evt) {
java.util.logging.Logger.getLogger(this.getClass().getName()).warning(getBasicInfo(result, evt));
java.util.logging.Logger.getLogger(this.getClass().getName()).warning(evt.getClaimInsutance());
}
private void log(String result, ClaimMessageEvent evt) {
java.util.logging.Logger.getLogger(this.getClass().getName()).info(getBasicInfo(result, evt));
}
private String getBasicInfo(String result, ClaimMessageEvent evt) {
String id = evt.getPatientId();
String nm = evt.getPatientName();
String sex = evt.getPatientSex();
String title = evt.getTitle();
String timeStamp = evt.getConfirmDate();
StringBuilder buf = new StringBuilder();
buf.append(result);
buf.append("[");
buf.append(id);
buf.append(" ");
buf.append(nm);
buf.append(" ");
buf.append(sex);
buf.append(" ");
buf.append(title);
buf.append(" ");
buf.append(timeStamp);
buf.append("]");
return buf.toString();
}
/**
* CLAIM 送信スレッド。
*/
protected class Consumer implements Runnable {
private final OrcaSocket orcaSocket;
public Consumer(OrcaSocket orcaSocket) {
this.orcaSocket = orcaSocket;
}
@Override
public void run() {
Thread thisThread = Thread.currentThread();
while (thisThread == sendThread) {
try {
// CLAIM Event を取得
ClaimMessageEvent claimEvent = (ClaimMessageEvent) getCLAIM();
String instance = claimEvent.getClaimInsutance();
try ( // Gets connection
Socket socket = orcaSocket.getSocket()) {
if ( socket == null ) {
int option = alertDialog(TT_CONNECTION_REJECT);
if (option == 1) {
warnLog("CLAIM Socket Error", claimEvent);
continue;
} else {
// push back to the queue
claimMessageEvent(claimEvent);
continue;
}
}
// Gets io stream
OutputStream out = socket.getOutputStream();
DataOutputStream dout = new DataOutputStream(out);
BufferedInputStream reader;
try (BufferedOutputStream writer = new BufferedOutputStream(dout)) {
InputStream in = socket.getInputStream();
DataInputStream din = new DataInputStream(in);
reader = new BufferedInputStream(din);
// Writes UTF8 data
writer.write(instance.getBytes(enc));
writer.write(EOT);
writer.flush();
// Reads result
int c = reader.read();
if (c == ACK) {
log("CLAIM ACK", claimEvent);
} else if (c == NAK) {
warnLog("received NAK", claimEvent);
}
}
reader.close();
}
} catch (IOException e) {
e.printStackTrace(System.err);
java.util.logging.Logger.getLogger(this.getClass().getName()).warning(e.getMessage());
alertDialog(TT_SENDING_TROUBLE);
} catch (InterruptedException e) {
java.util.logging.Logger.getLogger(this.getClass().getName()).warning("Interrupted sending CLAIM");
}
}
}
}
}