Package open.dolphin.client

Source Code of open.dolphin.client.ChartImpl$ReadOnlyState

package open.dolphin.client;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.EventHandler;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.prefs.Preferences;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import open.dolphin.delegater.DocumentDelegater;
import open.dolphin.helper.Task;
import open.dolphin.helper.WindowSupport;
import open.dolphin.impl.care.CareMapDocument;
import open.dolphin.impl.lbtest.LaboTestBean;
import open.dolphin.impl.pinfo.PatientInfoDocument;
import open.dolphin.infomodel.*;
import open.dolphin.inspector.DiagnosisInspector;
import open.dolphin.inspector.DocumentHistory;
import open.dolphin.inspector.MemoInspector;
import open.dolphin.inspector.PatientInspector;
import open.dolphin.project.Project;
import open.dolphin.ui.*;
import open.dolphin.util.GUIDGenerator;
import open.dolphin.util.PreferencesUtils;
import org.apache.commons.lang.time.DurationFormatUtils;
import org.apache.log4j.Logger;

/**
* 2号カルテ、傷病名、検査結果履歴等、患者の総合的データを提供するクラス。
*
* @author Kazushi Minagawa, Digital Globe, Inc.
*/
public class ChartImpl extends AbstractMainTool implements Chart, IInfoModel {
    private static final long serialVersionUID = 1L;

    /** カルテ状態の束縛プロパティ名 */
    public static final String CHART_STATE = "chartStateProp";

    //  Chart インスタンスを管理するstatic 変数
    private static ArrayList<ChartImpl> allCharts = new ArrayList<ChartImpl>(3);   
    // Chart 状態の通知を行うための static 束縛サポート
    private static PropertyChangeSupport boundSupport = new PropertyChangeSupport(new Object());   
    /// Document Plugin を格納する TabbedPane
    private PNSTabbedPane tabbedPane;   
    // Active になっているDocument Plugin
    private HashMap<String, ChartDocument> providers;   
    // 患者インスペクタ
    private PatientInspector inspector;   
    // Window Menu をサポートする委譲クラス
    private WindowSupport windowSupport;   
    // Toolbar
    private JPanel myToolPanel;
    // 検索状況等を表示する共通のパネル
    private StatusPanel statusPanel;
    // 患者来院情報
    private PatientVisitModel pvt;
    // Read Only の時 true
    private boolean readOnly;
    // Chart のステート
    private int chartState;
    // Chart内のドキュメントに共通の MEDIATOR
    private ChartMediator mediator;
    // State Mgr
    private StateMgr stateMgr;
    // MML送信 listener
    private MmlMessageListener mmlListener;
    // CLAIM 送信 listener
    private ClaimMessageListener claimListener;
    // このチャートの KarteBean
    private KarteBean karte;
    // GlassPane
    private BlockGlass blockGlass;
    // 最新の受診歴
    private LastVisit lastVisit;
    // Logger
    private Logger logger;

    private Preferences prefs;
    public static final String PN_FRAME = "chart.frame";

    // getDiagnosisDocument() に loadDocuments() が終わったことを知らせるオブジェクト
    public final boolean[] loadDocumentsDone = {false};
   
    /**
     * Creates new ChartService
     */
    public ChartImpl() {
        logger = ClientContext.getBootLogger();
        prefs = Project.getPreferences();
    }

    /**
     * このチャートのカルテを返す。
     * @return カルテ
     */
    @Override
    public KarteBean getKarte() {
        return karte;
    }

    /**
     * このチャートのカルテを設定する。
     * @param karte このチャートのカルテ
     */
    @Override
    public void setKarte(KarteBean karte) {
        this.karte = karte;
    }

    /**
     * Chart の JFrame を返す。
     * @return チャートウインドウno JFrame
     */
    @Override
    public MainFrame getFrame() {
        return windowSupport.getFrame();
    }

    /**
     * Chart内ドキュメントが共通に使用する Status パネルを返す。
     * @return IStatusPanel
     */
    @Override
    public StatusPanel getStatusPanel() {
        return statusPanel;
    }

    /**
     * Chart内ドキュメントが共通に使用する Status パネルを設定する。
     * @param statusPanel IStatusPanel
     */
    @Override
    public void setStatusPanel(StatusPanel statusPanel) {
        this.statusPanel = statusPanel;
    }

    /**
     * 来院情報を設定する。
     * @param pvt 来院情報
     */
    @Override
    public void setPatientVisit(PatientVisitModel pvt) {
        this.pvt = pvt;
    }

    /**
     * 来院情報を返す。
     * @return 来院情報
     */
    @Override
    public PatientVisitModel getPatientVisit() {
        return pvt;
    }

    /**
     * ReadOnly かどうかを返す。
     * @return ReadOnlyの時 true
     */
    @Override
    public boolean isReadOnly() {
        return readOnly;
    }

    /**
     * ReadOnly 属性を設定する。
     * @param readOnly ReadOnly user の時 true
     */
    @Override
    public void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;
    }

    /**
     * このチャートが対象としている患者モデルを返す。
     * @return チャートが対象としている患者モデル
     */
    @Override
    public PatientModel getPatient() {
        return getKarte().getPatient();
    }

    /**
     * このチャートが対象としている患者モデルを設定する。
     * @param patientModel チャートが対象とする患者モデル
     */
    public void setPatientModel(PatientModel patientModel) {
        this.getKarte().setPatient(patientModel);
    }

    /**
     * チャートのステート属性を返す。
     * @return チャートのステート属性
     */
    @Override
    public int getChartState() {
        return chartState;
    }

    /**
     * チャートのステートを設定する。
     * @param chartState チャートステート
     */
    @Override
    public void setChartState(int chartState) {
        this.chartState = chartState;
        //
        // インスタンスを管理する static オブジェクト
        // を使用し束縛リスナへ通知する
        //
        ChartImpl.fireChanged(this);
    }

    /**
     * チャート内で共通に使用する Mediator を返す。
     * @return ChartMediator
     */
    @Override
    public ChartMediator getChartMediator() {
        return mediator;
    }

    /**
     * チャート内で共通に使用する Mediator を設定する。
     * @param mediator ChartMediator
     */
    public void setChartMediator(ChartMediator mediator) {
        this.mediator = mediator;
    }

    /**
     * Menu アクションを制御する。
     */
    @Override
    public void enabledAction(String name, boolean enabled) {
        Action action = mediator.getAction(name);
        if (action != null) {
            action.setEnabled(enabled);
        } else {
            Toolkit.getDefaultToolkit().beep();
        }
    }

    /**
     * 文書ヒストリオブジェクトを返す。
     * @return 文書ヒストリオブジェクト DocumentHistory
     */
    @Override
    public DocumentHistory getDocumentHistory() {
        return inspector.getDocumentHistory();
    }
//pns^
    /**
     * 病名インスペクタを返す
     */
    public DiagnosisInspector getDiagnosisInspector() {
        return inspector.getDiagnosisInspector();
    }

    public LastVisit getLastVisit() {
        return lastVisit;
    }
//pns$

    /**
     * 引数で指定されたタブ番号のドキュメントを表示する。
     * @param 表示するドキュメントのタブ番号
     */
    @Override
    public void showDocument(int index) {
        int cnt = tabbedPane.getTabCount();
        if (index >= 0 && index <= cnt - 1 && index != tabbedPane.getSelectedIndex()) {
            tabbedPane.setSelectedIndex(index);
        }
    }

    /**
     * チャート内に未保存ドキュメントがあるかどうかを返す。
     * @return 未保存ドキュメントがある時 true
     */
    @Override
    public boolean isDirty() {

        boolean dirty = false;

        if (providers != null && providers.size() > 0) {
            Collection<ChartDocument> docs = providers.values();
            for (ChartDocument doc : docs) {
                if (doc.isDirty()) {
                    dirty = true;
                    break;
                }
            }
        }
        return dirty;
    }

    @Override
    public void start() {
       
        String sama = ClientContext.getString("sama");
        int maxEstimation = ClientContext.getInt("chart.maxEstimation"); //30000
        //int delay = ClientContext.getInt("chart.timerDelay"); // 200
        String message = "カルテオープン";
        String patientName = getPatientVisit().getPatient().getFullName() + sama;
        String note = patientName + "を開いています...";

        Task task = new Task<KarteBean>(null, message, note, maxEstimation) {

            @Override
            protected KarteBean doInBackground() throws Exception {
                logger.debug("CahrtImpl start task doInBackground");
                //
                // Database から患者のカルテを取得する
                //
                int past = Project.getPreferences().getInt(Project.DOC_HISTORY_PERIOD, -12);
                GregorianCalendar today = new GregorianCalendar();
                today.add(GregorianCalendar.MONTH, past);
                today.clear(Calendar.HOUR_OF_DAY);
                today.clear(Calendar.MINUTE);
                today.clear(Calendar.SECOND);
                today.clear(Calendar.MILLISECOND);
                DocumentDelegater ddl = new DocumentDelegater();
                KarteBean karteBean = ddl.getKarte(getPatientVisit().getPatient().getId(), today.getTime());
                return karteBean;
            }

            @Override
            protected void succeeded(KarteBean karteBean) {
                logger.debug("CahrtImpl start task succeeded");
                karteBean.setPatient(null);

                karteBean.setPatient(getPatientVisit().getPatient());
                setKarte(karteBean);
                initComponents();
                logger.debug("initComponents end");
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        getDocumentHistory().showHistory();
                    }
                });
            }
        };
        //task.setMillisToPopup(delay);
        task.execute();
    }

    /**
     * 患者のカルテを検索取得し、GUI を構築する。
     * このメソッドはバックグランドスレッドで実行される。
     */
    public void initComponents() {

        // このチャート の Frame を生成し初期化する。
        // Frame のタイトルを
        // 患者氏名(カナ):患者ID に設定する
        //

        // Frame と MenuBar を生成する
        String title = String.format("%s - %s(%s): %s",
                ClientContext.getString("chart.chartStr"),
                getPatient().getFullName(),
                getPatient().getKanaName().replace(" ", " "),
                getPatient().getPatientId());
       
        windowSupport = WindowSupport.create(title);

        // チャート用のメニューバーを得る
        JMenuBar myMenuBar = windowSupport.getMenuBar();

        // チャートの JFrame オブジェクトを得る
        final MainFrame frame = windowSupport.getFrame();
        frame.setName("chartFrame");

        // 患者インスペクタを生成する
        inspector = new PatientInspector(this);
        //pns inspector.getPanel().setBorder(BorderFactory.createEmptyBorder(7, 7, 5, 2)); // カット&トライ
        inspector.getPanel().setBorder(BorderFactory.createEmptyBorder()); // カット&トライ

        // Status パネルを生成する
        statusPanel = frame.getStatusPanel();
        //((JPanel)statusPanel).setBorder(BorderFactory.createEmptyBorder());
//pns^
        // lastVisit を設定する
        lastVisit = new LastVisit(this);
//pns$
        // Status パネルに表示する情報を生成する
        // カルテ登録日 Status パネルの右側に配置する
        String rdFormat = ClientContext.getString("common.dateFormat");         // yyyy-MM-dd
        String rdPrifix = ClientContext.getString("common.registeredDatePrefix");     // カルテ登録日:
        String patienIdPrefix = ClientContext.getString("common.registeredDatePatientIdPrefix"); // 患者ID:
        Date date = getKarte().getCreated();
        SimpleDateFormat sdf = new SimpleDateFormat(rdFormat);
        String created = sdf.format(date);
        //statusPanel.setRightInfo(rdPrifix + " " + created);           // カルテ登録日:yyyy/mm/dd
       
//pns^  status panel 設定
        // 患者ID Status パネルの左に配置する
        //statusPanel.setLeftInfo(patienIdPrefix + " " + getKarte().getPatient().getPatientId()); // 患者ID:xxxxxx
        statusPanel.add("", "message"); // key "message" の JLabel : AbstractChartDocument#enter と LaboTestBean で使う
        statusPanel.addGlue();
        statusPanel.addProgressBar();
        statusPanel.addSeparator();
        statusPanel.add(patienIdPrefix + " " + getKarte().getPatient().getPatientId());
        statusPanel.addSeparator();
        statusPanel.add(rdPrifix + " " + created);
        statusPanel.setTopLineAlpha(0.4f);
       
        Date pvtDate = ModelUtils.getDateTimeAsObject(pvt.getPvtDate());
        if (pvtDate != null && pvt.getState() == KarteState.CLOSE_NONE) { // window open 前に呼ばれる
            String waitingTime = DurationFormatUtils.formatPeriod(pvtDate.getTime(), new Date().getTime(), "HH:mm");
            //statusPanel.setRightInfo(rdPrifix + " " + created + "  待ち時間 " + waitingTime);
            statusPanel.addSeparator();
            statusPanel.add("待ち時間 " + waitingTime);
        }
        statusPanel.setMargin(4);
//pns$

        // ChartMediator を生成する
        mediator = new ChartMediator(this);

        // Menu を生成する
        MenuFactory appMenu = new MenuFactory();
        appMenu.setMenuSupports(getContext().getMenuSupport(), mediator);
        appMenu.build(myMenuBar);
        mediator.registerActions(appMenu.getActionMap());
        myToolPanel = appMenu.getToolPanelProduct();
        myToolPanel.add(inspector.getBasicInfoInspector().getPanel(), 0);
        JPanel spacer = new JPanel();
        spacer.setPreferredSize(new Dimension(24,16));
        spacer.setMinimumSize(new Dimension(24,16));
        spacer.setOpaque(false);
        myToolPanel.add(spacer, 1);

        //
        // このクラス固有のToolBarを生成する
        //
        ChartToolBar toolBar = new ChartToolBar(this);
        myToolPanel.add(toolBar);

        // Document プラグインのタブを生成する
        tabbedPane = loadDocuments();

        // 全体をレイアウトする
//      final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, inspector.getPanel(), tabbedPane);
//      splitPane.setName("splitPane");
       
//      JPanel myPanel = new JPanel();
//      myPanel.setOpaque(true);
//      myPanel.setLayout(new BorderLayout());
//      myPanel.add(myToolPanel, BorderLayout.NORTH);
//      myPanel.add(splitPane, BorderLayout.CENTER);
//pns$
//      myPanel.add((JPanel) statusPanel, BorderLayout.SOUTH);
//      frame.setContentPane(myPanel);

        MainFrame.CommandPanel comPanel = frame.getCommandPanel();
        myToolPanel.setOpaque(false);
        comPanel.add(myToolPanel);
        comPanel.setBackgroundColor(Color.BLACK, 0f, 0.1f);
       
        final MainFrame.MainPanel mainPanel = frame.getMainPanel();
        mainPanel.setLayout(new BorderLayout(0,0));
        mainPanel.add(tabbedPane, BorderLayout.CENTER);
        mainPanel.add(inspector.getPanel(), BorderLayout.WEST);
       
        // StateMgr を生成する
        stateMgr = new StateMgr();

        // BlockGlass を設定する
        blockGlass = new BlockGlass();
        frame.setGlassPane(blockGlass);

        // このチャートの Window にリスナを設定する
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                // CloseBox の処理を行う
                processWindowClosing();
            }

            @Override
            public void windowOpened(WindowEvent e) {
                // Window がオープンされた時の処理を行う
                ChartImpl.windowOpened(ChartImpl.this);
            }

            @Override
            public void windowClosed(WindowEvent e) {
                // Window がクローズされた時の処理を行う
                // stop で setVisible(false) を出した後に呼ばれる
                ChartImpl.windowClosed(ChartImpl.this);
            }

            @Override
            public void windowActivated(WindowEvent e) {
               
//pns^          マウスの場所に応じてフォーカス処理を行う
                Point p = frame.getMousePosition(true);
                Component c = null;
                String compName = null;
                if (p != null) c = frame.findComponentAt(p);

                // マウスが stamp にあればフォーカス移動しない
                // ドラッグ開始時にフォーカス移動があるとばたばたするので
                if (c instanceof ComponentHolder) {
                    //System.out.println("focus transition canceled");
                    return;
                }
                if (c != null) compName = c.getName();
               
                // マウスがメモにあれば,メモにフォーカス
                if (MemoInspector.NAME.equals(compName)) {
                    c.requestFocusInWindow();
                   
                // マウスが DiagnosisInspector にあれば何もしない
                } else if (DiagnosisInspector.NAME.equals(compName)) {
                    return;
               
                } else {
                   
//              それ以外は plugin の enter() で plugin ごとにフォーカス処理
                    //String key = String.valueOf(tabbedPane.getSelectedIndex());
                    String key = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
                    ChartDocument plugin = providers.get(key);
                    if (plugin != null) plugin.enter();
                }
//pns$
            }
        });

        // Frame の大きさをストレージからロードする
        int x = ClientContext.getInt("chart.frameX");
        int y = ClientContext.getInt("chart.frameY");
        int width = ClientContext.getInt("chart.frameWidth");
        int height = ClientContext.getInt("chart.frameHeight");
        Rectangle bounds = PreferencesUtils.getRectangle(prefs, PN_FRAME, new Rectangle(x, y, width, height));
       
        // フレームの表示位置を決める J2SE 5.0
        boolean locByPlatform = Project.getPreferences().getBoolean(Project.LOCATION_BY_PLATFORM, false);

        if (locByPlatform) {
            frame.setLocationByPlatform(true);
            frame.setSize(bounds.width, bounds.height);

        } else {
            frame.setLocationByPlatform(false);
            frame.setBounds(bounds);
        }
       
        // MML 送信 Queue
        if (Project.getSendMML()) {
            mmlListener = (MmlMessageListener) getContext().getPlugin("sendMml");
        }

        // CLAIM 送信 Queue
        if (Project.getSendClaim()) {
            claimListener = (ClaimMessageListener) getContext().getPlugin("sendClaim");
        }

        frame.setVisible(true);
       
        // ちらつき防止
        mainPanel.setVisible(false);
        EventQueue.invokeLater(new Runnable(){
            @Override
            public void run() {
                mainPanel.setVisible(true);
            }
        });
       
        // IME off
        IMEControl.setImeOff(getFrame());
       
//pns^  splitPane の左パネルを最小状態で開く
//        splitPane.setVisible(false); // divisionLocation が動く際のちらつきを防ぐ
//        EventQueue.invokeLater(new Runnable(){
//            public void run() {
//                //splitPane.putClientProperty("Quaqua.SplitPane.style", "bar");
//                splitPane.setDividerSize(6);
//                splitPane.setDividerLocation(inspector.getPanel().getMinimumSize().width);
//                splitPane.setVisible(true);
//            }
//        });
//pns$
    }

    /**
     * MML送信リスナを返す。
     * @return MML送信リスナ
     */
    public MmlMessageListener getMMLListener() {
        return mmlListener;
    }

    /**
     * CLAIM送信リスナを返す。
     * @return CLAIM送信リスナ
     */
    public ClaimMessageListener getCLAIMListener() {
        return claimListener;
    }

    /**
     * メニューを制御する。
     */
    public void controlMenu() {
        stateMgr.controlMenu();
    }

    /**
     * ドキュメントタブを生成する。
     */
//pns    private JTabbedPane loadDocuments() {
    private PNSTabbedPane loadDocuments() {

        providers = new HashMap<String, ChartDocument>();
       
        PNSTabbedPane tab = new PNSTabbedPane();
        tab.getButtonPanel().setPadding(new Dimension(0,4));
        tab.getButtonPanel().setBackgroundColor(Color.BLACK, 0.1f, 0.2f);
        tab.getButtonPanel().setBottomLineAlpha(0.4f);

        ChartDocument[] plugin = new ChartDocument[5];
        plugin[0] = new DocumentBridgeImpl();
        plugin[1] = new DiagnosisDocument();
        plugin[2] = new LaboTestBean();
        plugin[3] = new CareMapDocument();
        plugin[4] = new PatientInfoDocument();

        for (int index = 0; index < plugin.length; index++) {

            if (index == 0 ) {
//          if (index == 0 || index == 1) { // DiagnosisInspector を作ったので傷病名も先に読むようにした → 検索からオープンしたとき,getDocumentHistory が終わってないので lastVisit がとれない!
                plugin[index].setContext(this);
                plugin[index].start();
            }

            tab.addTab(plugin[index].getTitle(), plugin[index].getUI());
            // tab のタイトルをキーにする
            providers.put(plugin[index].getTitle(), plugin[index]);
        }

        // ゼロ番目を選択しておき changeListener を機能させる
        tab.setSelectedIndex(0);
        //
        // tab に プラグインを遅延生成するためのの ChangeListener を追加する
        //
        tab.addChangeListener(EventHandler.create(ChangeListener.class, this, "tabChanged", ""));

        // getDiagnosisDocument() に loadDocuments が終わったことを通知する
        synchronized(loadDocumentsDone) {
            loadDocumentsDone[0] = true;
            loadDocumentsDone.notify();
        }
        return tab;
    }

    /**
     * ドキュメントタブにプラグインを遅延生成し追加する。
     */
    public void tabChanged(ChangeEvent e) {

        //
        // 選択されたタブ番号に対応するプラグインをテーブルから検索する
        //
        int index = tabbedPane.getSelectedIndex();
//      String key = String.valueOf(index);
        String key = tabbedPane.getTitleAt(index);
        ChartDocument plugin = providers.get(key);
       
        if (plugin.getContext() == null) {
            //
            // まだ生成されていないプラグインを生成する
            //
            plugin.setContext(ChartImpl.this);
            plugin.start();           
            tabbedPane.setComponentAt(index, plugin.getUI());
//pns   これだと,start() した後,enter() が呼ばれない
        } // else {
        //
        // 既に生成済みプラグインの場合は enter() をコールする
        //
        plugin.enter();
    }
   
    /**
     * DiangosisInspector に病名 drop できるようにする
     * DiagnosisInspector に DiagnosisDocument を教えるためのメソッド
     * DiagnosisDocument ができあがってからオブジェクトを返す
     * @return
     */
    public DiagnosisDocument getDiagnosisDocument() {
        // loadDocuments されて,providers がセットされるまで待つ
        synchronized(loadDocumentsDone) {
            if (!loadDocumentsDone[0]) {
                try{ loadDocumentsDone.wait();}
                catch (InterruptedException e){}
            }
        }
       
        DiagnosisDocument doc = (DiagnosisDocument) providers.get("傷病名");
        if (doc.getContext() == null) {
            doc.setContext(ChartImpl.this);
            doc.start();
        }
        return doc;
    }
   
    /**
     * 新規カルテを作成する。
     */   
    public void newKarte() {

        logger.debug("newKarte() in ChartImpl starts");

        // ReadOnly なら開かない
        if (isReadOnly()) return;

        // 新規カルテ作成はひとつだけ masuda
        if (toFrontNewKarteIfPresent()) return;
        // masuda

        String dept = getPatientVisit().getDeptNoTokenize();
        String deptCode = getPatientVisit().getDepartmentCode();
        String insuranceUid = getPatientVisit().getInsuranceUid();

        // 新規ドキュメントのタイプ=2号カルテと可能なオプションを設定する
        String docType = IInfoModel.DOCTYPE_KARTE;
        Chart.NewKarteOption option = null;
        KarteViewer base = null;

        //ChartDocument bridgeOrViewer = providers.get("0");
        ChartDocument bridgeOrViewer = providers.get("参 照");

        if (bridgeOrViewer instanceof DocumentBridgeImpl) {
            // Chart画面のタブパネル
            logger.debug("bridgeOrViewer instanceof DocumentBridgeImpl");
            DocumentBridgeImpl bridge = (DocumentBridgeImpl) bridgeOrViewer;
            base = bridge.getBaseKarte();

        } else if (bridgeOrViewer instanceof KarteDocumentViewer) {
            logger.debug("bridgeOrViewer instanceof KarteDocumentViewer");
            KarteDocumentViewer viwer = (KarteDocumentViewer) bridgeOrViewer;
            base = viwer.getBaseKarte();
        } else {
            return;
        }

        if (base != null) {
            logger.debug("base != null");
            if (base.getDocType().equals(IInfoModel.DOCTYPE_KARTE)) {
                logger.debug("base.getDocType().equals(IInfoModel.DOCTYPE_KARTE");
                option = Chart.NewKarteOption.BROWSER_COPY_NEW;
            } else {
                // ベースがあても2号カルテでない場合
                logger.debug("base.getDocType().equals(IInfoModel.DOCTYPE_S_KARTE");
                option = Chart.NewKarteOption.BROWSER_NEW;
            }

        } else {
            // ベースのカルテがない場合
            logger.debug("base == null");
            option = Chart.NewKarteOption.BROWSER_NEW;
        }

        //
        // 新規カルテ作成時に確認ダイアログを表示するかどうか
        //
        NewKarteParams params = null;

        if (prefs.getBoolean(Project.KARTE_SHOW_CONFIRM_AT_NEW, true)) {

            // 新規カルテダイアログへパラメータを渡し、コピー新規のオプションを制御する
            logger.debug("show newKarteDialog");
            params = getNewKarteParams(docType, option, null, dept, deptCode, insuranceUid);

        } else {
            // 保険、作成モード、配置方法を手動で設定する
            params = new NewKarteParams(option);
            params.setDocType(docType);
            params.setDepartment(dept);
            params.setDepartmentCode(deptCode);

            // 保険
            PVTHealthInsuranceModel[] ins = getHealthInsurances();
            params.setPVTHealthInsurance(ins[0]);
            if (insuranceUid != null) {
                for (int i = 0; i < ins.length; i++) {
                    if (ins[i].getGUID() != null) {
                        if (insuranceUid.equals(ins[i].getGUID())) {
                            params.setPVTHealthInsurance(ins[i]);
                            break;
                        }
                    }
                }
            }

            // 作成モード
            switch (option) {

                case BROWSER_NEW:
                    params.setCreateMode(Chart.NewKarteMode.EMPTY_NEW);
                    break;

                case BROWSER_COPY_NEW:
                    int cMode = prefs.getInt(Project.KARTE_CREATE_MODE, 0);
                    if (cMode == 0) {
                        params.setCreateMode(Chart.NewKarteMode.EMPTY_NEW);
                    } else if (cMode == 1) {
                        params.setCreateMode(Chart.NewKarteMode.APPLY_RP);
                    } else if (cMode == 2) {
                        params.setCreateMode(Chart.NewKarteMode.ALL_COPY);
                    }
                    break;
            }

            // 配置方法
            params.setOpenFrame(prefs.getBoolean(Project.KARTE_PLACE_MODE, true));

        }

        // キャンセルした場合はリターンする
        if (params == null) {
            return;
        }

        logger.debug("returned newKarteDialog");
        DocumentModel editModel = null;
        KarteEditor editor = null;
       
        // Baseになるカルテがあるかどうかでモデルの生成が異なる
        if (params.getCreateMode() == Chart.NewKarteMode.EMPTY_NEW) {
            logger.debug("empty new is selected");
            editModel = getKarteModelToEdit(params);
        } else {
            logger.debug("copy new is selected");
            editModel = getKarteModelToEdit(base.getModel(), params);
        }

//pns^ 新規カルテにいろいろモジュールを入れる
        StampTreeModules stm = new StampTreeModules(this);
        // 初診・再診 stampTreeModule を自動入力する
        ModuleModel mm = stm.getBaseCharge();
        if (mm != null) editModel.addModule(mm);

        // 初期テキストスタンプ挿入
        if (stm.isShoshin()) {
            mm = stm.getTextStamp("テンプレート(初診)");
            if (mm != null) editModel.addModule(mm);
        } else {
            mm = stm.getTextStamp("テンプレート(再診)");
            if (mm != null) editModel.addModule(mm);
        }
//pns$
        editor = createEditor();
        editor.setModel(editModel);
        editor.setEditable(true);
        editor.setMode(KarteEditor.DOUBLE_MODE);
      
        if (params.isOpenFrame()) {
            final EditorFrame editorFrame = new EditorFrame();
            editorFrame.setChart(this);
            editorFrame.setKarteEditor(editor);
//pns^      editorFrame.start();
            SwingUtilities.invokeLater(new Runnable(){
                @Override
                public void run() {
                    // Quaqua 6.5 になってから,こうしないと,editor がフォーカスを取っても,その後 ChartImpl に制御がうつって,
                    // せっかく取った focus を ChartImpl に取り返されてしまうようになった
                    editorFrame.start();
                }
            });
//pns$
        } else {
            editor.setContext(this);
            editor.initialize();
            editor.start();
            this.addChartDocument(editor, params);
        }
    }

    /**
     * EmptyNew 新規カルテのモデルを生成する。
     * @param params 作成パラメータセット
     * @return 新規カルテのモデル
     */
    public DocumentModel getKarteModelToEdit(NewKarteParams params) {

        // カルテモデルを生成する
        DocumentModel model = new DocumentModel();
       
        //
        // DocInfoを設定する
        //
        DocInfoModel docInfo = model.getDocInfo();

        // docId 文書ID
        docInfo.setDocId(GUIDGenerator.generate(docInfo));

        // 生成目的
        docInfo.setPurpose(PURPOSE_RECORD);

        // DocumentType
        docInfo.setDocType(params.getDocType());

//        //
//        // 診療科を設定する
//        // 受付情報から得ている
//        //
//        String dept = params.getDepartment();
//        docInfo.setDepartmentDesc(dept); // department
//       
//        // 診療科コード
//        // 受付からとっていない場合....
//        String deptCode = params.getDepartmentCode();
//        if (deptCode == null) {
//            docInfo.setDepartment(MMLTable.getDepartmentCode(dept)); // dept.code
//        }
        docInfo.setDepartmentDesc(getPatientVisit().getDeptNoTokenize());
        docInfo.setDepartment(getPatientVisit().getDepartmentCode());

        // 健康保険を設定する
        PVTHealthInsuranceModel insurance = params.getPVTHealthInsurance();
        docInfo.setHealthInsurance(insurance.getInsuranceClassCode());
        docInfo.setHealthInsuranceDesc(insurance.toString());
        docInfo.setHealthInsuranceGUID(insurance.getGUID());

        // Versionを設定する
        VersionModel version = new VersionModel();
        version.initialize();
        docInfo.setVersionNumber(version.getVersionNumber());

        //
        // Document の Status を設定する
        // 新規カルテの場合は none
        //
        docInfo.setStatus(STATUS_NONE);

        return model;
    }

    /**
     * コピーして新規カルテを生成する場合のカルテモデルを生成する。
     * @param oldModel コピー元のカルテモデル
     * @param params 生成パラメータセット
     * @return 新規カルテのモデル
     */
    public DocumentModel getKarteModelToEdit(DocumentModel oldModel, NewKarteParams params) {

        //
        // 新規モデルを作成し、表示されているモデルの内容をコピーする
        //
        DocumentModel newModel = new DocumentModel();
        boolean applyRp = params.getCreateMode() == Chart.NewKarteMode.APPLY_RP ? true : false;
        copyModel(oldModel, newModel, applyRp);

        //
        // 新規カルテの DocInfo を設定する
        //
        DocInfoModel docInfo = newModel.getDocInfo();

        // 文書ID
        docInfo.setDocId(GUIDGenerator.generate(docInfo));

        // 生成目的
        docInfo.setPurpose(PURPOSE_RECORD);

        // DocumentType
        docInfo.setDocType(params.getDocType());

        //
        // 診療科を設定する 受付情報から設定する
        //
        String dept = params.getDepartment();
        docInfo.setDepartmentDesc(dept);

//        // 診療科コード
//        // 受付からとっていない場合....
//        String deptCode = params.getDepartmentCode();
//        if (deptCode == null) {
//            docInfo.setDepartment(MMLTable.getDepartmentCode(dept)); // dept.code
//        }       
        docInfo.setDepartmentDesc(getPatientVisit().getDeptNoTokenize());
        docInfo.setDepartment(getPatientVisit().getDepartmentCode());

        // 健康保険を設定する
        PVTHealthInsuranceModel insurance = params.getPVTHealthInsurance();
        docInfo.setHealthInsurance(insurance.getInsuranceClassCode());
        //docInfo.setHealthInsuranceDesc(insurance.getInsuranceClass());
        docInfo.setHealthInsuranceDesc(insurance.toString());
        docInfo.setHealthInsuranceGUID(insurance.getGUID());

        // Versionを設定する
        VersionModel version = new VersionModel();
        version.initialize();
        docInfo.setVersionNumber(version.getVersionNumber());

        //
        // Document の Status を設定する
        // 新規カルテの場合は none
        //
        docInfo.setStatus(STATUS_NONE);

        return newModel;
    }

    /**
     * 修正の場合のカルテモデルを生成する。
     * @param oldModel 修正対象のカルテモデル
     * @return 新しい版のカルテモデル
     */
    public DocumentModel getKarteModelToEdit(DocumentModel oldModel) {

        // 修正対象の DocInfo を取得する
        DocInfoModel oldDocInfo = oldModel.getDocInfo();

        // 新しい版のモデルにモジュールと画像をコピーする
        DocumentModel newModel = new DocumentModel();
        copyModel(oldModel, newModel, false);

        //
        // 新しい版の DocInfo を設定する
        //
        DocInfoModel newInfo = newModel.getDocInfo();

        // 文書ID
        newInfo.setDocId(GUIDGenerator.generate(newInfo));

        // 新しい版の firstConfirmDate = 元になる版の firstConfirmDate
        newInfo.setFirstConfirmDate(oldDocInfo.getFirstConfirmDate());

        // docType = old one
        newInfo.setDocType(oldDocInfo.getDocType());

        // purpose = old one
        newInfo.setPurpose(oldDocInfo.getPurpose());

        //
        // タイトルも引き継ぐ
        //
        newInfo.setTitle(oldDocInfo.getTitle());

        //
        // 診療科を設定する
        // 元になる版の情報を利用する
        //
        newInfo.setDepartmentDesc(oldDocInfo.getDepartmentDesc());
        newInfo.setDepartment(oldDocInfo.getDepartment());

        //
        // 健康保険を設定する
        // 元になる版の情報を利用する
        //
        newInfo.setHealthInsuranceDesc(oldDocInfo.getHealthInsuranceDesc());
        newInfo.setHealthInsurance(oldDocInfo.getHealthInsurance());
        newInfo.setHealthInsuranceGUID(oldDocInfo.getHealthInsuranceGUID());

        //
        // 親文書IDを設定する
        //
        newInfo.setParentId(oldDocInfo.getDocId());
        newInfo.setParentIdRelation(PARENT_OLD_EDITION);

        //
        // old PK を設定する
        //
        newInfo.setParentPk(oldModel.getId());

        //
        // Versionを設定する
        // new = old + 1.0
        VersionModel newVersion = new VersionModel();
        newVersion.setVersionNumber(oldDocInfo.getVersionNumber());
        newVersion.incrementNumber(); // version number ++
        newInfo.setVersionNumber(newVersion.getVersionNumber());

        //
        // Document Status を設定する
        // 元になる版の status (Final | Temporal | Modified)
        //
        newInfo.setStatus(oldDocInfo.getStatus());

        return newModel;
    }

    /**
     * カルテエディタを生成する。
     * @return カルテエディタ
     */
    public KarteEditor createEditor() {
        KarteEditor editor = null;
        try {
            editor = new KarteEditor();
            editor.addMMLListner(mmlListener);
            editor.addCLAIMListner(claimListener);
        } catch (TooManyListenersException e) {
            logger.warn(e);
            editor = null;
        }
        return editor;
    }

    //
    // モデルをコピーする
    // ToDO 参照ではいけない
    // DocInfo の設定はない
    //
    private void copyModel(DocumentModel oldModel, DocumentModel newModel, boolean applyRp) {

        //
        // 前回処方を適用する場合
        //
        if (applyRp) {
            Collection<ModuleModel> modules = oldModel.getModules();
            if (modules != null) {
                Collection<ModuleModel> apply = new ArrayList<ModuleModel>(5);

                for (ModuleModel bean : modules) {
                    IInfoModel model = bean.getModel();
                    if (model instanceof ClaimBundle) {
                        //
                        // 処方かどうかを判定する
                        //
                        if (((ClaimBundle) model).getClassCode().startsWith("2")) {
                            apply.add(bean);
                        }
//pns^                  ついでに,処置もコピー
                        if (((ClaimBundle) model).getClassCode().startsWith("4")) {
                            apply.add(bean);
                        }
//pns$
                    }
                }

                if (!apply.isEmpty()) {
                    newModel.setModules(apply);
                }
            }

        } else {
            // 全てコピー
            newModel.setModules(oldModel.getModules());
            newModel.setSchema(oldModel.getSchema());
        }
    }

    /**
     * カルテ作成時にダアイログをオープンし、保険を選択させる。
     *
     * @return NewKarteParams
     */
    public NewKarteParams getNewKarteParams(String docType, Chart.NewKarteOption option, MainFrame f, String dept, String deptCode, String insuranceUid) {

        NewKarteParams params = new NewKarteParams(option);
        params.setDocType(docType);
        params.setDepartment(dept);
        params.setDepartmentCode(deptCode);

        // 患者の健康保険コレクション
        Collection<PVTHealthInsuranceModel> insurances = pvt.getPatient().getPvtHealthInsurances();

        // コレクションが null の場合は自費保険を追加する
        if (insurances == null || insurances.isEmpty()) {
            insurances = new ArrayList<PVTHealthInsuranceModel>(1);
            PVTHealthInsuranceModel model = new PVTHealthInsuranceModel();
            model.setInsuranceClass(INSURANCE_SELF);
            model.setInsuranceClassCode(INSURANCE_SELF_CODE);
            model.setInsuranceClassCodeSys(INSURANCE_SYS);
            insurances.add(model);
        }

        // 保険コレクションを配列に変換し、パラメータにセットする
        // ユーザがこの中の保険を選択する
        PVTHealthInsuranceModel[] insModels = insurances.toArray(new PVTHealthInsuranceModel[insurances.size()]);
        params.setInsurances(insModels);
        int index = 0;
        if (insuranceUid != null) {
            for (int i = 0; i < insModels.length; i++) {
                if (insModels[i].getGUID() != null) {
                    if (insModels[i].getGUID().equals(insuranceUid)) {
                        index = i;
                        break;
                    }
                }
            }
        }
        params.setInitialSelectedInsurance(index);

        String text = option == Chart.NewKarteOption.BROWSER_MODIFY
//pns           ? resMap.getString("modifyKarteTitle")
//pns           : resMap.getString("newKarteTitle");
                ? ClientContext.getString("chart.modifyKarteTitle")
                : ClientContext.getString("chart.newKarteTitle");

        text = ClientContext.getFrameTitle(text);

        // モーダルダイアログを表示する
        MainFrame frame = f != null ? f : getFrame();
        NewKarteDialog od = new NewKarteDialog(frame, text);
        od.setValue(params);
        od.start();

        // 戻り値をリターンする
        params = (NewKarteParams) od.getValue();
        return params;
    }

    /**
     * 患者の健康保険を返す。
     * @return 患者の健康保険配列
     */
    @Override
    public PVTHealthInsuranceModel[] getHealthInsurances() {

        // 患者の健康保険
        Collection<PVTHealthInsuranceModel> insurances = pvt.getPatient().getPvtHealthInsurances();

        if (insurances == null || insurances.isEmpty()) {
            insurances = new ArrayList<PVTHealthInsuranceModel>(1);
            PVTHealthInsuranceModel model = new PVTHealthInsuranceModel();
            model.setInsuranceClass(INSURANCE_SELF);
            model.setInsuranceClassCode(INSURANCE_SELF_CODE);
            model.setInsuranceClassCodeSys(INSURANCE_SYS);
            insurances.add(model);
        }

        return insurances.toArray(new PVTHealthInsuranceModel[insurances.size()]);
    }

    /**
     * 選択された保険を特定する
     * UUID が見つかったらそれを返す。なかったら最初に見つかった保険を返す。
     * @param uuid 選択された保険のUUID
     * @return 選択された保険
     */
    @Override
    public PVTHealthInsuranceModel getHealthInsuranceToApply(String uuid) {

        // 患者の健康保険
        Collection<PVTHealthInsuranceModel> insurances = pvt.getPatient().getPvtHealthInsurances();
        // insurance model がなければ null を返す
        if (uuid == null || insurances == null || insurances.isEmpty()) return null;
       
        PVTHealthInsuranceModel ret = null;

        for (PVTHealthInsuranceModel hm : insurances) {
            if (ret == null) ret = hm;

            if (uuid.equals(hm.getGUID())) {
                ret = hm;
                //System.out.println("CharImpl: found uuid to apply = " + uuid);
                break;
            }
        }

        return ret;
    }
   
    /**
     * タブにドキュメントを追加する。
     * @param doc 追加するドキュメント
     * @param params 追加するドキュメントの情報を保持する NewKarteParams
     */
    public void addChartDocument(ChartDocument doc, NewKarteParams params) {
        String title = null;
        if (params.getPVTHealthInsurance() != null) {
            title = getTabTitle(params.getDepartment(), params.getPVTHealthInsurance().getInsuranceClass());
        } else {
            title = getTabTitle(params.getDepartment(), null);
        }
        tabbedPane.addTab(title, doc.getUI());
        int index = tabbedPane.getTabCount() - 1;
        providers.put(String.valueOf(index), doc);
        tabbedPane.setSelectedIndex(index);
    }

    /**
     * タブにドキュメントを追加する。
     * @param title タブタイトル
     */
    public void addChartDocument(ChartDocument doc, String title) {
        tabbedPane.addTab(title, doc.getUI());
        int index = tabbedPane.getTabCount() - 1;
        providers.put(String.valueOf(index), doc);
        tabbedPane.setSelectedIndex(index);
    }

    /**
     * 新規カルテ用のタブタイトルを作成する
     * @param insurance 保険名
     * @return タブタイトル
     */
    public String getTabTitle(String dept, String insurance) {
        String[] depts = dept.split("\\s*,\\s*");
        StringBuilder buf = new StringBuilder();
//pns   buf.append(resMap.getString("newKarteTabTitle"));
        buf.append(ClientContext.getString("chart.newKarteTabTitle"));
        if (insurance != null) {
            buf.append("(");
            buf.append(depts[0]);
            buf.append("・");
            buf.append(insurance);
            buf.append(")");
        }
        return buf.toString();
    }

    /**
     * 新規文書作成で選択されたプラグインを起動する。
     *
     * @param pluginClass 起動するプラグインのクラス名
     */
    private void invokePlugin(String pluginClass) {

        try {
            NChartDocument doc = (NChartDocument) Class.forName(
                    pluginClass,
                    true,
                    ClientContext.getPluginClassLoader()).newInstance();
           
            if (doc instanceof KarteEditor) {
                String dept = getPatientVisit().getDeptNoTokenize();
                String deptCode = getPatientVisit().getDepartmentCode();
                String insuranceUid = getPatientVisit().getInsuranceUid();
                Chart.NewKarteOption option = Chart.NewKarteOption.BROWSER_NEW;
                String docType = IInfoModel.DOCTYPE_S_KARTE;
                NewKarteParams params = new NewKarteParams(option);
                params.setDocType(docType);
                params.setDepartment(dept);
                params.setDepartmentCode(deptCode);

                //
                // 保険
                //
                PVTHealthInsuranceModel[] ins = getHealthInsurances();
                params.setPVTHealthInsurance(ins[0]);
                if (insuranceUid != null) {
                    for (int i = 0; i < ins.length; i++) {
                        if (ins[i].getGUID() != null) {
                            if (insuranceUid.equals(ins[i].getGUID())) {
                                params.setPVTHealthInsurance(ins[i]);
                                break;
                            }
                        }
                    }
                }

                DocumentModel editModel = getKarteModelToEdit(params);
                KarteEditor editor = (KarteEditor) doc;
                editor.setModel(editModel);
                editor.setEditable(true);
                editor.setContext(this);
                editor.setMode(KarteEditor.SINGLE_MODE);
                editor.initialize();
                editor.start();
                this.addChartDocument(editor, params);
               
            } else {
                doc.setContext(this);
                doc.start();
                addChartDocument(doc, doc.getTitle());
            }

        } catch (ClassNotFoundException e) { System.out.println("ChartImpl.java: " + e);
        } catch (InstantiationException e) { System.out.println("ChartImpl.java: " + e);
        } catch (IllegalAccessException e) { System.out.println("ChartImpl.java: " + e); }
    }
   
    /**
     * カルテ以外の文書を作成する。
     */
//pns^  自分的には使わないので削除した
/*    public void newDocument() {
       
        // 拡張ポイント新規文書のプラグインをリストアップし、
        // リストで選択させる
        ArrayList<NameValuePair> documents = new ArrayList<NameValuePair>(3);
        PluginLister<NChartDocument> lister = PluginLister.list(NChartDocument.class, ClientContext.getPluginClassLoader());
        LinkedHashMap<String, String> nproviders = lister.getProviders();
        if (nproviders != null) {
            Iterator<String> iter = nproviders.keySet().iterator();
            while (iter.hasNext()) {
                String cmd = iter.next();
                String clsName = nproviders.get(cmd);
                NameValuePair pair = new NameValuePair(cmd, clsName);
                documents.add(pair);
                logger.debug(cmd + " = " + clsName);
            }
        }

        if (documents.size() == 0) {
            logger.debug("No plugins");
            return;
        }
       
        // docs アイコンをラベルへInjectionする
        JLabel newDocsLabel = new JLabel();
        newDocsLabel.setName("newDocsLabel");
//pns   resMap.injectComponent(newDocsLabel);
        newDocsLabel.setIcon(GUIConst.ICON_DOCUMENT_GENERIC_32);

        final JList docList = new JList(documents.toArray());
//pns   docList.setCellRenderer(new StripeRenderer());
       
        JPanel panel = new JPanel(new BorderLayout(7, 0));
        panel.add(newDocsLabel,BorderLayout.WEST);
        panel.add(docList, BorderLayout.CENTER);
        panel.setBorder(BorderFactory.createEmptyBorder(6,6,5,5));
        JPanel content = new JPanel(new BorderLayout());
        content.add(panel, BorderLayout.CENTER);
        content.setBorder(BorderFactory.createTitledBorder("作成する文書"));

        final JButton okButton = new JButton("了解");
        final JButton cancelButton = new JButton("取消し");
        Object[] options = new Object[]{okButton, cancelButton};

        JOptionPane jop = new JOptionPane(
                content,
                JOptionPane.PLAIN_MESSAGE,
                JOptionPane.DEFAULT_OPTION,
                null,
                options,
                okButton);

        final JDialog dialog = jop.createDialog(getFrame(), ClientContext.getFrameTitle("新規文書作成"));
        dialog.addWindowListener(new WindowAdapter() {

            @Override
            public void windowOpened(WindowEvent e) {
                docList.requestFocusInWindow();
            }
        });

        okButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                dialog.setVisible(false);
                dialog.dispose();
                NameValuePair pair = (NameValuePair) docList.getSelectedValue();
                String clsName = pair.getValue();
                invokePlugin(clsName);
            }
        });
        okButton.setEnabled(false);

        cancelButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                dialog.setVisible(false);
                dialog.dispose();
            }
        });

        docList.addListSelectionListener(new ListSelectionListener() {

            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting() == false) {
                    int index = docList.getSelectedIndex();
                    if (index >= 0) {
                        okButton.setEnabled(true);
                    }
                }
            }
        });

        dialog.setVisible(true);
    }
*/
//pns$

    /**
     * 全てのドキュメントを保存する。
     * @param dirtyList 未保存ドキュメントのリスト
     */
    private void saveAll(java.util.List<UnsavedDocument> dirtyList) {

        if (dirtyList == null || dirtyList.isEmpty()) {
            return;
        }

        for (UnsavedDocument undoc : dirtyList) {
            if (undoc.isNeedSave()) {
                //ChartDocument doc = providers.get(String.valueOf(undoc.getIndex()));
                ChartDocument doc = providers.get(tabbedPane.getTitleAt(undoc.getIndex()));
                if (doc != null && doc.isDirty()) {
                    tabbedPane.setSelectedIndex(undoc.getIndex());
                    doc.save();
                }
            }
        }
    }

    /**
     * ドキュメントのなかにdirtyのものがあるかどうかを返す。
     * @return dirtyの時true
     */
    private java.util.List<UnsavedDocument> dirtyList() {
        java.util.List<UnsavedDocument> ret = null;
        int count = tabbedPane.getTabCount();
        for (int i = 0; i < count; i++) {
            //ChartDocument doc = providers.get(String.valueOf(i));
            ChartDocument doc = providers.get(tabbedPane.getTitleAt(i));
            if (doc != null && doc.isDirty()) {
                if (ret == null) {
                    ret = new ArrayList<UnsavedDocument>(3);
                }
                ret.add(new UnsavedDocument(i, doc));
            }
        }
        return ret;
    }

    /**
     * CloseBox がクリックされた時の処理を行う。
     */
    public void processWindowClosing() {
        close();
    }

    /**
     * チャートウインドウを閉じる。
     */
    @Override
    public void close() {

//pns^  この患者の EditorFrame が開いたままなら,閉じる努力をする。EditorFame 保存がキャンセルされたらあきらめる。
        java.util.List<Chart> editorFrames = new ArrayList<Chart>(EditorFrame.getAllEditorFrames());
        if (editorFrames.size() > 0) {
            String patientId = this.getKarte().getPatient().getPatientId();
            for (Chart chart : editorFrames) {
                String id = chart.getKarte().getPatient().getPatientId();
                if (patientId.equals(id)) {
                    chart.close();

                    if (EditorFrame.getAllEditorFrames().contains(chart)) {
                        // EditorFrame が消えていないと言うことは,キャンセルされたと言うこと。この場合,chart 終了もキャンセル。
                        // logger.info("ChartImpl#close : canceled");
                        return;
                    }
                }
            }
        }
//pns$
        //
        // 未保存ドキュメント(病名等)がある場合はダイアログを表示し
        // 保存するかどうかを確認する
        //
        java.util.List<UnsavedDocument> dirtyList = dirtyList();

        if (dirtyList != null && dirtyList.size() > 0) {

//pns       String saveAll = resMap.getString("unsavedtask.saveText");     // 保存;
//pns       String discard = resMap.getString("unsavedtask.discardText");  // 破棄;
//pns       String question = resMap.getString("unsavedtask.question");    // 未保存のドキュメントがあります。保存しますか ?
//pns       String title = resMap.getString("unsavedtask.title");          // 未保存処理
            String saveAll = ClientContext.getString("unsavedtask.saveText");     // 保存;
            String discard = ClientContext.getString("unsavedtask.discardText")// 破棄;
            String question = ClientContext.getString("unsavedtask.question");    // 未保存のドキュメントがあります。保存しますか ?
            String title = ClientContext.getString("unsavedtask.title");          // 未保存処理
            String cancelText = (String) UIManager.get("OptionPane.cancelButtonText");

            Object[] message = new Object[dirtyList.size() + 1];
            message[0] = (Object) question;
            int index = 1;
            for (UnsavedDocument doc : dirtyList) {
                message[index++] = doc.getCheckBox();
            }

//pns^      すでに JSheet が出ている場合は,toFront してリターン
            if (MyJSheet.isAlreadyShown(getFrame())) {
                getFrame().toFront();
                return;
            }
//pns       int option = JOptionPane.showOptionDialog(
            int option = MyJSheet.showOptionDialog(
                    getFrame(),
                    message,
                    ClientContext.getFrameTitle(title),
                    JOptionPane.DEFAULT_OPTION,
                    JOptionPane.QUESTION_MESSAGE,
                    null,
                    new String[]{saveAll, discard, cancelText},
                    saveAll);

            switch (option) {
                case 0:
                    // save
                    saveAll(dirtyList);
                    // DiagnosisDocument が isValidOutcome でなければ,close を中止する
                    if (!getDiagnosisDocument().isValidOutcome()) break;
                    stop();
                    break;

                case 1:
                    // discard
                    stop();
                    break;

                case 2:
                    // cancel
                    break;
            }
        } else {
            stop();
        }
    }

    @Override
    public void stop() {

        if (providers != null) {
            for (Iterator<String> iter = providers.keySet().iterator(); iter.hasNext();) {
                ChartDocument doc = providers.get(iter.next());
                if (doc != null) {
                    doc.stop();
                }
            }
            providers.clear();
        }
        mediator.dispose();
        inspector.dispose();
       
        PreferencesUtils.putRectangle(prefs, PN_FRAME, getFrame().getBounds());

//pns^  DBTask が残っていると Chart にアクセスしてくるので,dispose する前に thread を shutdown する
//      Mar., 2010 メモや診断がサーバにセーブされない事態が発生! ここのせい??
//      DatabaseExecutor.restart();
//pns$
        getFrame().setVisible(false); // ここで windowClosed が呼ばれる
        getFrame().setJMenuBar(null);
        getFrame().dispose();
    }

    private abstract class ChartState {

        public ChartState() {
        }

        public abstract void controlMenu();
    }

    /**
     * ReadOnly ユーザの State クラス。
     */
    private final class ReadOnlyState extends ChartState {

        public ReadOnlyState() {
        }

        /**
         * 新規カルテ作成及び修正メニューを disable にする。
         */
        @Override
        public void controlMenu() {
            mediator.getAction(GUIConst.ACTION_NEW_KARTE).setEnabled(false);
            mediator.getAction(GUIConst.ACTION_MODIFY_KARTE).setEnabled(false);
        }
    }

    /**
     * 保険証がない場合の State クラス。
     */
    private final class NoInsuranceState extends ChartState {

        public NoInsuranceState() {
        }

        @Override
        public void controlMenu() {
            mediator.getAction(GUIConst.ACTION_NEW_KARTE).setEnabled(false);
        }
    }

    /**
     * 通常の State クラス。
     */
    private final class OrdinalyState extends ChartState {

        public OrdinalyState() {
        }

        @Override
        public void controlMenu() {
            mediator.getAction(GUIConst.ACTION_NEW_KARTE).setEnabled(true);
        }
    }

    /**
     * State Manager クラス。
     */
    private final class StateMgr {

        private ChartState readOnlyState = new ReadOnlyState();
        private ChartState noInsuranceState = new NoInsuranceState();
        private ChartState ordinalyState = new OrdinalyState();
        private ChartState currentState;

        public StateMgr() {
            if (isReadOnly()) {
                enterReadOnlyState();
            } else {
                enterOrdinalyState();
            }
        }

        public void enterReadOnlyState() {
            currentState = readOnlyState;
            currentState.controlMenu();
        }

        public void enterNoInsuranceState() {
            currentState = noInsuranceState;
            currentState.controlMenu();
        }

        public void enterOrdinalyState() {
            currentState = ordinalyState;
            currentState.controlMenu();
        }

        public void controlMenu() {
            currentState.controlMenu();
        }
    }

    /**** Chart Instance を管理するための static クラス **/
    /**
     * オープンしている全インスタンスを保持するリストを返す。
     * @return オープンしている ChartPlugin のリスト
     */
    public static ArrayList<ChartImpl> getAllChart() {
        return allCharts;
    }

    /**
     * チャートステートの束縛リスナを登録する。
     * @param prop 束縛プロパティ名
     * @param l 束縛リスナ
     */
    public static void addPropertyChangeListener(String prop,
            PropertyChangeListener l) {
        boundSupport.addPropertyChangeListener(prop, l);
    }

    /**
     * チャートステートの束縛リスナを削除する。
     * @param prop 束縛プロパティ名
     * @param l 束縛リスナ
     */
    public static void removePropertyChangeListener(String prop,
            PropertyChangeListener l) {
        boundSupport.removePropertyChangeListener(prop, l);
    }

    /**
     * チャートウインドウのオープンを通知する。
     * CLOSE -> OPEN に変換する操作,ReadOnly の場合は WatingList に通知しない
     * PatientSearchImpl で開いた場合など,pvt.id=0 の場合は WatingList に通知しない
     * @param opened オープンした Chart(=this)
     */
    public static void windowOpened(ChartImpl opened) {

        // インスタンスを保持するリストへ追加する
        allCharts.add(opened);

        PatientVisitModel model = opened.getPatientVisit();
        int oldState = model.getState();
        // pvt status を変更する(close -> open)
        int newState = KarteState.toOpenState(oldState);
        model.setState(newState);
       
        if (!opened.isReadOnly() && model.getId() != 0) {
            boundSupport.firePropertyChange(ChartImpl.CHART_STATE, null, model);
        }
        // このあと,pvt.state は karteBean 読み込みがあればサーバデータでリストアされる
    }

    /**
     * チャートウインドウのクローズを通知する。
     * OPEN -> CLOSE に変更する操作   ReadOnly のときも WatingList に通知する
     * PatientSearchImpl で開いた場合など,pvt.id=0 の場合は WatingList に通知しない
     * @param closed クローズした Chart(=this)
     */
    public static void windowClosed(ChartImpl closed) {

        // pvt status を変更する(open -> close)
        PatientVisitModel model = closed.getPatientVisit();
        if (closed.isReadOnly()) {
            model.setState(KarteState.READ_ONLY);
        } else {
            int oldState = model.getState();
            boolean isEmpty = new DocumentPeeker(model).isKarteEmpty();
            int newState = KarteState.toClosedState(oldState, isEmpty);
            model.setState(newState);
        }
        // WatingListImpl に通知する
        // 書き込み時の ReadOnly 対応は WatingList 側で施行
        if (model.getId() != 0) {
            boundSupport.firePropertyChange(ChartImpl.CHART_STATE, null, model);
        }

        // 最後にインスタンスリストから取り除く
        boolean succeeded = allCharts.remove(closed);
        if (!succeeded) {
            // カルテが登録されていなかったと言うことで,ありえない
            throw new RuntimeException("Chart is lost!");
        }
    }

    /**
     * チャート状態の変化を通知する。
     * @param 変化のあった ChartPlugin
     */
    public static void fireChanged(ChartImpl changed) {
        PatientVisitModel model = changed.getPatientVisit();
        model.setState(changed.getChartState());
    }
   
//pns^
    /**
     * 開いている全ての chart を閉じる
     */
    //public static void closeAll() {
    //    for (ChartImpl chart : allCharts) {
    //        chart.close();
    //    }
    //}

    /**
     * Document が modify用に既に開かれていたら toFront する
     * masuda 先生の docAlreadyOpened のパクリ
     * @param DocumentModel doc
     * @return toFront できたら true
     */
    public boolean toFrontDocumentIfPresent(DocumentModel baseDocumentModel) {
        if (baseDocumentModel == null || baseDocumentModel.getDocInfo() == null) return false;
        long baseDocPk = baseDocumentModel.getDocInfo().getDocPk();
        List<Chart> editorFrames = EditorFrame.getAllEditorFrames();
        if (!editorFrames.isEmpty()) {
            for (Chart chart : editorFrames) {
                EditorFrame frame = (EditorFrame) chart;
                long parentDocPk = frame.getParentDocPk();
                if (baseDocPk == parentDocPk) {
                    // parentPkが同じEditorFrameがある場合はFrameをtoFrontする
                    chart.getFrame().setExtendedState(java.awt.Frame.NORMAL);
                    chart.getFrame().toFront();
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * NewKarte が既に開かれていたら toFront する
     * masuda 先生の newKarteAlreadyOpened のパクリ
     * @return toFront できたら true
     */
    private boolean toFrontNewKarteIfPresent() {
        List<Chart> editorFrames = EditorFrame.getAllEditorFrames();
        if (!editorFrames.isEmpty()) {
            String patientId = this.getKarte().getPatient().getPatientId();
            for (Chart chart : editorFrames) {
                // 新規カルテだとDocInfoのstatusは"N"
                EditorFrame ef = (EditorFrame) chart;
                String status = ef.getDocInfoStatus();
                String id = chart.getKarte().getPatient().getPatientId();
                if (patientId.equals(id) && IInfoModel.STATUS_NONE.equals(status)) {
                    // 新規カルテのEditorFrameがある場合はFrameをtoFrontする
                    chart.getFrame().setExtendedState(Frame.NORMAL);
                    chart.getFrame().toFront();
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * カルテを前に出す
     * @param pvt
     */
    public static void toFront(PatientVisitModel pvt) {
        if (pvt == null) return;
        toFront(pvt.getPatient());
    }

    public static void toFront(PatientModel patient) {
        if (patient == null) return;
        long ptId = patient.getId();
        if (patient != null) {
            for (ChartImpl chart : allCharts) {
                if (chart.getPatient().getId() == ptId) {
                    chart.getFrame().toFront();
                    return;
                }
            }
        }
    }
    /**
     * カルテがあるかどうか調べる
     * @param pvt
     */
    public static boolean isKarteOpened(PatientVisitModel pvt) {
        if (pvt == null) return false;
        return isKarteOpened(pvt.getPatient());
    }
   
    public static boolean isKarteOpened(PatientModel patient) {
        if (patient == null) return false;
        long ptId = patient.getId();
        for (ChartImpl chart : allCharts) {
            if (chart.getPatient().getId() == ptId) {
                return true;
            }
        }
        return false;
    }
//pns$
}
TOP

Related Classes of open.dolphin.client.ChartImpl$ReadOnlyState

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.