OSDN Git Service

[自動予約一覧]検索条件、録画設定の取得とファイルへの保存まで
authorpeeweedee <peeweedee@users.sourceforge.jp>
Thu, 20 Jun 2013 14:36:04 +0000 (23:36 +0900)
committerpeeweedee <peeweedee@users.sourceforge.jp>
Thu, 20 Jun 2013 14:36:04 +0000 (23:36 +0900)
35 files changed:
TinyBannavi/05_history.txt
TinyBannavi/env/ChannelConvert.dat
TinyBannavi/src/tainavi/AbsAutoReserveListView.java
TinyBannavi/src/tainavi/AbsListedView.java
TinyBannavi/src/tainavi/AbsPaperColorsDialog.java
TinyBannavi/src/tainavi/AbsReserveDialog.java
TinyBannavi/src/tainavi/AbsToolBar.java
TinyBannavi/src/tainavi/AutoReserveInfo.java
TinyBannavi/src/tainavi/AutoReserveInfoList.java
TinyBannavi/src/tainavi/Bounds.java
TinyBannavi/src/tainavi/ChannelCode.java
TinyBannavi/src/tainavi/ClipboardInfoList.java
TinyBannavi/src/tainavi/CommonUtils.java
TinyBannavi/src/tainavi/Env.java
TinyBannavi/src/tainavi/FieldUtils.java
TinyBannavi/src/tainavi/FieldUtils2.java [new file with mode: 0644]
TinyBannavi/src/tainavi/HDDRecorder.java
TinyBannavi/src/tainavi/HDDRecorderChangeEvent.java [new file with mode: 0644]
TinyBannavi/src/tainavi/HDDRecorderList.java
TinyBannavi/src/tainavi/HDDRecorderListener.java [new file with mode: 0644]
TinyBannavi/src/tainavi/HDDRecorderSelectable.java [new file with mode: 0644]
TinyBannavi/src/tainavi/HDDRecorderSelectionEvent.java [new file with mode: 0644]
TinyBannavi/src/tainavi/HDDRecorderUtils.java
TinyBannavi/src/tainavi/PaperColorsMap.java
TinyBannavi/src/tainavi/PlugIn_RecDIGA_DMR_BWT2100.java
TinyBannavi/src/tainavi/PlugIn_RecRD_EDCB.java
TinyBannavi/src/tainavi/RecorderInfoList.java
TinyBannavi/src/tainavi/SearchGroupList.java
TinyBannavi/src/tainavi/TVProgramList.java
TinyBannavi/src/tainavi/TVProgramUtils.java
TinyBannavi/src/tainavi/TextValueMap.java [new file with mode: 0644]
TinyBannavi/src/tainavi/VWHDDRecorderSelectionEvent.java [deleted file]
TinyBannavi/src/tainavi/VWHDDRecorderSelectionListener.java [deleted file]
TinyBannavi/src/tainavi/Viewer.java
TinyBannavi/src/todo.txt

index 85adc52..7d73869 100644 (file)
@@ -15,6 +15,7 @@
  ・(レコーダ対応[DIGA BWT2100/BZT710/720]) 録画結果一覧の取得に仮対応(最大3ページ60タイトルまでなので、仮)\r
 ■バグ修正\r
  ・(その他) SwingWorkerで生成したサブスレッド内で想定外のruntime exceptionが発生するとサブスレッドがログも出さずに死んでしまってエラー原因を調査できなかったが、ログが出るように仕掛けをしたのでその仕掛けがうまく動くようなら今後改善が進んでいくはず\r
+ ・(予約ダイアログ) 類似予約テーブルで「類似予約を選択しない」を選んでも、番組ID取得ボタンがリセットされない場合がある問題を修正\r
 \r
 3.22.1β+1.5.12(2013-05-23)\r
 ■変更点\r
index dbf80e1..d0ecba5 100644 (file)
 "CS296 TBSチャンネル1","TBSチャンネル1"\r
 "CS296 TBSチャンネル1","TBSチャンネル1"\r
 \r
+"CS297 TBSチャンネル2","TBSチャンネル2"\r
+\r
 "CS298 テレ朝チャンネルHD","テレ朝チャンネル"\r
 "CS298 テレ朝チャンネル1 ドラマ・バラエティ・アニメ","テレ朝チャンネル"\r
 \r
index 8986945..9a3812f 100644 (file)
@@ -9,19 +9,19 @@ import java.util.HashMap;
 import javax.swing.JPanel;\r
 import javax.swing.JScrollPane;\r
 import javax.swing.JTable;\r
+import javax.swing.event.ChangeEvent;\r
+import javax.swing.event.ChangeListener;\r
 import javax.swing.table.DefaultTableColumnModel;\r
 import javax.swing.table.DefaultTableModel;\r
 import javax.swing.table.TableColumn;\r
 import javax.swing.table.TableModel;\r
 \r
-import com.sun.corba.se.impl.oa.poa.AOMEntry;\r
-\r
 \r
 /**\r
  * 自動予約一覧タブのクラス\r
  * @since 3.22.2β\r
  */\r
-public abstract class AbsAutoReserveListView extends JPanel implements VWHDDRecorderSelectionListener {\r
+public abstract class AbsAutoReserveListView extends JPanel implements HDDRecorderListener {\r
 \r
        private static final long serialVersionUID = 1L;\r
        \r
@@ -72,7 +72,7 @@ public abstract class AbsAutoReserveListView extends JPanel implements VWHDDReco
        \r
        public static enum AutoRsvColumn {\r
                EXEC            ("実行",                      50),\r
-               TITLE           ("タイトル",                300),\r
+               TITLE           ("タイトル",                500),\r
                CHNAME          ("チャンネル名",  150),\r
                ;\r
 \r
@@ -227,33 +227,49 @@ public abstract class AbsAutoReserveListView extends JPanel implements VWHDDReco
                rowheaderModel_list.fireTableDataChanged();\r
        }\r
        \r
+       \r
        /*******************************************************************************\r
-        * ã\83ªã\82¹ã\83\8aã\83¼\r
+        * ã\83\8fã\83³ã\83\89ã\83©â\80\95ã\83¡ã\82½ã\83\83ã\83\89\r
         ******************************************************************************/\r
        \r
-       // ツールバーでレコーダの選択イベントが発生\r
+       /**\r
+        * ツールバーでレコーダの選択イベントが発生\r
+        */\r
        @Override\r
-       public void recorderSelected(VWHDDRecorderSelectionEvent e) {\r
+       public void valueChanged(HDDRecorderSelectionEvent e) {\r
                if (debug) System.out.println(DBGID+"recorder selection rised");\r
                \r
                // 選択中のレコーダ情報を保存する\r
-               ev_recsel = e;\r
+               src_recsel = (HDDRecorderSelectable) e.getSource();\r
                \r
                // テーブルを書き換える\r
                redrawByRecorderSelected();\r
        }\r
        \r
-       @Override\r
-       public String getSelectedRecorder() {\r
-               return ( ev_recsel!=null ? ev_recsel.getSelected() : null );\r
+       private String getSelectedRecorder() {\r
+               return ( src_recsel!=null ? src_recsel.getSelectedId() : null );\r
+       }\r
+       \r
+       private HDDRecorderList getSelectedRecorderList() {\r
+               return ( src_recsel!=null ? src_recsel.getSelectedList() : null );\r
        }\r
        \r
+       private HDDRecorderSelectable src_recsel;\r
+       \r
+       \r
+       /**\r
+        * レコーダ情報の変更イベントが発生\r
+        */\r
        @Override\r
-       public HDDRecorderList getSelectedRecorderList() {\r
-               return ( ev_recsel!=null ? ev_recsel.getSelectedRecorderList() : null );\r
+       public void stateChanged(HDDRecorderChangeEvent e) {\r
+               // テーブルをリフレッシュする処理\r
+               redrawByRecorderSelected();\r
        }\r
        \r
-       private VWHDDRecorderSelectionEvent ev_recsel;\r
+       /*******************************************************************************\r
+        * リスナー\r
+        ******************************************************************************/\r
+       \r
        \r
        /*******************************************************************************\r
         * コンポーネント\r
index ffd9a6e..4a59148 100644 (file)
@@ -2777,7 +2777,7 @@ public abstract class AbsListedView extends JPanel implements VWTimerRiseListene
                                }\r
                        }\r
                        //trKeys = newTrKeys;\r
-                       CommonUtils.FieldCopy(trKeys, newTrKeys);\r
+                       FieldUtils.deepCopy(trKeys, newTrKeys);\r
                        trKeys.save();\r
                        \r
                        if ( oList.size() < oCnt ) {\r
@@ -2909,7 +2909,7 @@ public abstract class AbsListedView extends JPanel implements VWTimerRiseListene
                                }\r
                        }\r
                        //srKeys = newSrKeys;\r
-                       CommonUtils.FieldCopy(srKeys, newSrKeys);\r
+                       FieldUtils.deepCopy(srKeys, newSrKeys);\r
                        srKeys.save();\r
                        \r
                        // ツリーを更新\r
@@ -3157,7 +3157,7 @@ public abstract class AbsListedView extends JPanel implements VWTimerRiseListene
                                }\r
                        }\r
                        //extKeys = newExtKeys;\r
-                       CommonUtils.FieldCopy(extKeys, newExtKeys);\r
+                       FieldUtils.deepCopy(extKeys, newExtKeys);\r
                        extKeys.save();\r
                        \r
                        // ツリーを更新\r
index dea440f..c91295e 100644 (file)
@@ -245,9 +245,9 @@ abstract class AbsPaperColorsDialog extends JDialog {
                                        System.err.println("[DEBUG] before orig papercolorsmap "+key+"="+origpc.get(key));\r
                                }\r
                        }\r
-                       CommonUtils.FieldCopy(tmpenv, origenv);\r
-                       CommonUtils.FieldCopy(tmpbnd, origbnd);\r
-                       CommonUtils.FieldCopy(tmppc, origpc);\r
+                       FieldUtils.deepCopy(tmpenv, origenv);\r
+                       FieldUtils.deepCopy(tmpbnd, origbnd);\r
+                       FieldUtils.deepCopy(tmppc, origpc);\r
                        setColors();\r
                        setFonts();\r
                        setBounds();\r
index e0e65a5..4039bce 100644 (file)
@@ -108,6 +108,9 @@ abstract class AbsReserveDialog extends JDialog {
        \r
        private static final int LIKERSVTABLE_NOTSELECTED = -1;\r
        \r
+       private static final String LIKERSVID_NONE                      = "(類似予約なし)";\r
+       private static final String LIKERSVID_NOTSELECTED       = "類似予約を選択しない";\r
+       \r
        // レイアウト関連\r
        \r
        private static final int TITLE_WIDTH = 370;\r
@@ -2118,9 +2121,15 @@ abstract class AbsReserveDialog extends JDialog {
                                myavs = getSelectedAVs(vals.hide_tvd.genre, mychname, myrec.getRecorderId());\r
                                \r
                                if ( ContentIdEDCB.isValid(vals.hide_tvd.progid) ) {\r
+                                       // 番組表の番組IDがあれば利用する\r
                                        vals.hide_content_id = vals.hide_tvd.progid;\r
                                        setGetEventIdButton(vals.hide_content_id,false);\r
                                }\r
+                               else {\r
+                                       // なければ空にする\r
+                                       vals.hide_content_id = null;\r
+                                       setGetEventIdButton(vals.hide_content_id,true);\r
+                               }\r
                        }\r
                        \r
                        // 状況に応じて"更新"ボタンの有効無効を変更する\r
@@ -3275,10 +3284,10 @@ abstract class AbsReserveDialog extends JDialog {
                        if ( row == 0 ) {\r
                                if ( column == LikeRsvColumn.TITLE.ordinal() ) {\r
                                        if ( vals.likeRsvList.size() == 0 ) {\r
-                                               return "(類似予約なし)";\r
+                                               return LIKERSVID_NONE;\r
                                        }\r
                                        else {\r
-                                               return "類似予約を選択しない";\r
+                                               return LIKERSVID_NOTSELECTED;\r
                                        }\r
                                }\r
                                else if ( column == LikeRsvColumn.START.ordinal() ) {\r
index 3080b72..7de9574 100644 (file)
@@ -30,8 +30,6 @@ import javax.swing.JSlider;
 import javax.swing.JTextField;\r
 import javax.swing.JToggleButton;\r
 import javax.swing.JToolBar;\r
-import javax.swing.event.ChangeEvent;\r
-import javax.swing.event.ChangeListener;\r
 \r
 import tainavi.HDDRecorder.RecType;\r
 import tainavi.SearchKey.TargetId;\r
@@ -45,7 +43,7 @@ import tainavi.Viewer.LoadRsvedFor;;
  * ツールバーのクラス\r
  * @version 3.16.3β Viewer.classから分離\r
  */\r
-public abstract class AbsToolBar extends JToolBar {\r
+public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectable {\r
 \r
        private static final long serialVersionUID = 1L;\r
 \r
@@ -151,11 +149,6 @@ public abstract class AbsToolBar extends JToolBar {
 \r
        private static final String ICONFILE_PULLDOWNMENU       = "icon/down-arrow.png";\r
 \r
-       // ページャーに追加する特殊選択肢\r
-       \r
-       private final String SELECTED_ALL = "すべて";\r
-       private final String SELECTED_PICKUP = "ピックアップのみ";\r
-       \r
        // ツールチップ関連\r
        \r
        private static final String TIPS_KEYWORD                        = "<HTML><B>検索ボックスの書式</B><BR>検索:(オプション1) (オプション2) キーワード <BR>過去ログ検索:開始日[(YYYY/)MM/DD] 終了日[(YYYY/)MM/DD] (オプション2) キーワード<BR>過去ログ閲覧:日付[YYYY/MM/DD]<BR>※オプション1:@filter..絞込検索(過去ログは対象外)<BR>※オプション2:#title..番組名一致、#detail..番組詳細一致、なし..番組名&番組詳細一致<BR></HTML>";\r
@@ -229,10 +222,16 @@ public abstract class AbsToolBar extends JToolBar {
        private JButton jButton_help = null;\r
 \r
        // レコーダ選択イベント発生時にキックするリスナーのリスト\r
-       private final ArrayList<VWHDDRecorderSelectionListener> lsnrs_recsel = new ArrayList<VWHDDRecorderSelectionListener>();\r
+       private final ArrayList<HDDRecorderListener> lsnrs_recsel = new ArrayList<HDDRecorderListener>();\r
+       \r
+       // 各種情報の変更イベント発生時にキックするリスナーのリスト\r
+       private final ArrayList<HDDRecorderListener> lsnrs_infochg = new ArrayList<HDDRecorderListener>();\r
        \r
        // その他\r
        \r
+       private String selectedRecorderId = null;\r
+       private HDDRecorderList selectedRecorderList = null;\r
+       \r
        private boolean statusarea_shown = bounds.getShowStatus();\r
        \r
        /*******************************************************************************\r
@@ -589,15 +588,16 @@ public abstract class AbsToolBar extends JToolBar {
         * @return 「すべて」が選択されている場合はNULL、「ピックアップ」が選択されている場合は""を返す\r
         */\r
        public String getSelectedRecorder() {\r
+               \r
                if ( jComboBox_select_recorder == null ) {\r
-                       return VWHDDRecorderSelectionListener.SELECTED_ALL;\r
+                       return HDDRecorderListener.SELECTED_ALL;\r
                }\r
                String recId = (String)jComboBox_select_recorder.getSelectedItem();\r
-               if ( recId.equals(SELECTED_ALL) ) {\r
-                       return VWHDDRecorderSelectionListener.SELECTED_ALL;\r
+               if ( recId.equals(HDDRecorder.SELECTED_ALL) ) {\r
+                       return HDDRecorderListener.SELECTED_ALL;\r
                }\r
-               else if ( recId.equals(SELECTED_PICKUP) ) {\r
-                       return VWHDDRecorderSelectionListener.SELECTED_PICKUP;\r
+               else if ( recId.equals(HDDRecorder.SELECTED_PICKUP) ) {\r
+                       return HDDRecorderListener.SELECTED_PICKUP;\r
                }\r
                \r
                return recId;\r
@@ -610,7 +610,7 @@ public abstract class AbsToolBar extends JToolBar {
        public void setSelectedRecorder(String myself) {\r
                if ( jComboBox_select_recorder != null ) {\r
                        jComboBox_select_recorder.setSelectedItem(null);\r
-                       jComboBox_select_recorder.setSelectedItem((myself == null)?(SELECTED_ALL):(myself));\r
+                       jComboBox_select_recorder.setSelectedItem((myself == null)?(HDDRecorder.SELECTED_ALL):(myself));\r
                }\r
        }\r
        \r
@@ -620,9 +620,12 @@ public abstract class AbsToolBar extends JToolBar {
        public void updateRecorderComboBox() {\r
                \r
                jComboBox_select_recorder.removeItemListener(il_recorderSelected);\r
+\r
+               // レコーダの選択情報をリセット\r
+               setSelectedRecorderInfo(null);\r
                \r
                jComboBox_select_recorder.removeAllItems();\r
-               jComboBox_select_recorder.addItem(SELECTED_ALL);\r
+               jComboBox_select_recorder.addItem(HDDRecorder.SELECTED_ALL);\r
                for (HDDRecorder r : recorders) {\r
                        switch ( r.getType() ) {\r
                        case RECORDER:\r
@@ -635,7 +638,7 @@ public abstract class AbsToolBar extends JToolBar {
                                break;\r
                        }\r
                }\r
-               jComboBox_select_recorder.addItem(SELECTED_PICKUP);\r
+               jComboBox_select_recorder.addItem(HDDRecorder.SELECTED_PICKUP);\r
 \r
                jComboBox_select_recorder.addItemListener(il_recorderSelected);\r
        }\r
@@ -689,16 +692,79 @@ public abstract class AbsToolBar extends JToolBar {
         * リスナー追加/削除\r
         ******************************************************************************/\r
        \r
-       public void addVWHDDRecorderSelectionListener(VWHDDRecorderSelectionListener l) {\r
+       /**\r
+        * レコーダ選択イベントリスナー\r
+        */\r
+       @Override\r
+       public void addHDDRecorderSelectionListener(HDDRecorderListener l) {\r
                if ( ! lsnrs_recsel.contains(l) ) {\r
                        lsnrs_recsel.add(l);\r
                }\r
        }\r
 \r
-       public void removeVWHDDRecorderSelectionListener(VWHDDRecorderSelectionListener l) {\r
+       @Override\r
+       public void removeHDDRecorderSelectionListener(HDDRecorderListener l) {\r
                lsnrs_recsel.remove(l);\r
        }\r
+       \r
+       @Override\r
+       public String getSelectedId() {\r
+               return selectedRecorderId;\r
+       }\r
+       \r
+       @Override\r
+       public HDDRecorderList getSelectedList() {\r
+               return selectedRecorderList;\r
+       }\r
+       \r
+       /**\r
+        * 情報変更イベントリスナー(番組表リロード、レコーダ情報リロード、etc)\r
+        */\r
+       @Override\r
+       public void addHDDRecorderChangeListener(HDDRecorderListener l) {\r
+               if ( ! lsnrs_infochg.contains(l) ) {\r
+                       lsnrs_infochg.add(l);\r
+               }\r
+       }\r
+\r
+       @Override\r
+       public void removeHDDRecorderChangeListener(HDDRecorderListener l) {\r
+               lsnrs_infochg.remove(l);\r
+       }\r
+\r
+       \r
+       /*******************************************************************************\r
+        * イベントトリガー\r
+        ******************************************************************************/\r
+\r
+       /**\r
+        * レコーダ選択イベントトリガー\r
+        */\r
+       private void fireHDDRecorderSelected() {\r
+               \r
+               HDDRecorderSelectionEvent e = new HDDRecorderSelectionEvent(this);\r
+\r
+               if (debug) System.out.println(DBGID+"recorder selection rised.");\r
+\r
+               for ( HDDRecorderListener l : lsnrs_recsel ) {\r
+                       l.valueChanged(e);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * レコーダ選択イベントトリガー\r
+        */\r
+       private void fireHDDRecorderChanged() {\r
+               \r
+               HDDRecorderChangeEvent e = new HDDRecorderChangeEvent(this);\r
+\r
+               if (debug) System.out.println(DBGID+"change rised.");\r
 \r
+               for ( HDDRecorderListener l : lsnrs_infochg ) {\r
+                       l.stateChanged(e);\r
+               }\r
+       }\r
+       \r
        /*******************************************************************************\r
         * リスナー\r
         ******************************************************************************/\r
@@ -792,36 +858,43 @@ public abstract class AbsToolBar extends JToolBar {
                }\r
        };\r
 \r
-       // レコーダコンボボックスが選択された\r
+       /**\r
+        * レコーダコンボボックスが選択された\r
+        */\r
        private final ItemListener il_recorderSelected = new ItemListener() {\r
                @Override\r
                public void itemStateChanged(ItemEvent e) {\r
                        if (e.getStateChange() == ItemEvent.SELECTED) {\r
+                               \r
+                               // 選択中のレコーダ情報を保存\r
+                               setSelectedRecorderInfo(getSelectedRecorder());\r
+                               \r
+                               // 各タブへの反映\r
+                               \r
                                // 旧ロジック\r
                                recorderSelectorChanged();\r
                                \r
                                // 新ロジック\r
-                               {\r
-                                       String selected = getSelectedRecorder();\r
-                                       HDDRecorderList recs = recorders.findInstance(selected);\r
-                                       \r
-                                       VWHDDRecorderSelectionEvent ev = new VWHDDRecorderSelectionEvent(e.getSource(),selected,recs);\r
-\r
-                                       if (debug) System.out.println(DBGID+"recorder selection rised selected="+selected);\r
-\r
-                                       for ( VWHDDRecorderSelectionListener l : lsnrs_recsel ) {\r
-                                               l.recorderSelected(ev);\r
-                                       }\r
-                               }\r
+                               fireHDDRecorderSelected();\r
                        }\r
                        \r
                }\r
        };\r
        \r
+       /**\r
+        * 選択中のレコーダ情報を保存\r
+        */\r
+       private void setSelectedRecorderInfo(String recid) {\r
+               selectedRecorderId = recid;\r
+               selectedRecorderList = recorders.findInstance(recid);\r
+       }\r
+       \r
        // 予約一覧の再取得\r
        private final ActionListener al_reloadReserved = new ActionListener(){\r
                public void actionPerformed(ActionEvent e){\r
                        reLoadRdReserve(getSelectedRecorder());\r
+                       \r
+                       fireHDDRecorderChanged();               // 各タブへの反映\r
                }\r
        };\r
        \r
index 3c6e129..bf00432 100644 (file)
@@ -2,12 +2,26 @@ package tainavi;
 \r
 import java.util.ArrayList;\r
 \r
+import taiSync.ReserveInfo;\r
+import tainavi.TVProgram.ProgOption;\r
 import tainavi.TVProgram.ProgSubgenre;\r
 \r
 \r
 public class AutoReserveInfo implements Cloneable {\r
        \r
        /*******************************************************************************\r
+        * コンストラクタ\r
+        ******************************************************************************/\r
+\r
+       // デフォルトコンストラクタ\r
+       public AutoReserveInfo() {\r
+               super();\r
+               \r
+               this.timeslots = new ArrayList<String>(TIMESLOTSIZE);\r
+       }\r
+       \r
+       \r
+       /*******************************************************************************\r
         * clone(ディープコピー)\r
         ******************************************************************************/\r
        \r
@@ -16,14 +30,14 @@ public class AutoReserveInfo implements Cloneable {
                try {\r
                        AutoReserveInfo p = (AutoReserveInfo) super.clone();\r
                        \r
-                       p.Channels = new ArrayList<String>();\r
-                       for ( String ch : Channels ) {\r
-                               p.Channels.add(ch);\r
+                       p.chNames = new ArrayList<String>();\r
+                       for ( String ch : chNames ) {\r
+                               p.chNames.add(ch);\r
                        }\r
                        \r
-                       p.Subgenres = new ArrayList<ProgSubgenre>();\r
-                       for ( ProgSubgenre sg : Subgenres ) {\r
-                               p.Subgenres.add(sg);\r
+                       p.subgenres = new ArrayList<ProgSubgenre>();\r
+                       for ( ProgSubgenre sg : subgenres ) {\r
+                               p.subgenres.add(sg);\r
                        }\r
                        \r
                        return p;\r
@@ -35,56 +49,93 @@ public class AutoReserveInfo implements Cloneable {
 \r
        \r
        /*******************************************************************************\r
-        * メンバー変\r
+        * \r
         ******************************************************************************/\r
-\r
-       private String Id;\r
        \r
-       private String Label;\r
+       public static final int TIMESLOTSIZE = 7;\r
+       \r
        \r
-       private String IncludeKeyword;\r
-       private String ExcludeKeyword;\r
+       /*******************************************************************************\r
+        * メンバー変数\r
+        ******************************************************************************/\r
+\r
+       /*\r
+        *  HIDDEN PARAMS\r
+        */\r
        \r
-       private Boolean RegularExpression;\r
-       private Boolean FazzySearch;\r
-       private Boolean TitleOnly;\r
+       private String id;                                              // ID ※レコーダが一意に割り当てるID\r
        \r
        /*\r
-        * TvRock : CHコードはコントローラの値と同じ(ただしHEX)\r
-        * EDCB : CHコードは予約操作時と同じ\r
+        *  SHOWN PARAMS\r
         */\r
-       private ArrayList<String> Channels = new ArrayList<String>();                                                   // *D\r
-       private ArrayList<ProgSubgenre> Subgenres = new ArrayList<TVProgram.ProgSubgenre>();    // *D\r
+       \r
+       private String label;                                   // 一覧表示用\r
+       \r
+       private String keyword;                                 // 絞り込みキーワード\r
+       private String exKeyword;                               // 追加キーワード ※[E]排他キーワード、[T]詳細キーワード\r
+       \r
+       private boolean regularExpression;              // キーワードは正規表現\r
+       private boolean fazzySearch;                    // あいまい検索する\r
+       private boolean titleOnly;                              // 検索対象はタイトルのみ[E]\r
+\r
+       private boolean uniqTimeslot;                   // 全曜日に同じ時間範囲を利用する ※[E]選択可、[T]true強制\r
+       private ArrayList<String> timeslots;    // 時間範囲(7日分) ※使用しない曜日にはnullを設定する\r
+       \r
+       private boolean recordedCheck;                  // 録画済み無効[E]\r
+       private int recordedCheckTerm;                  // 録画済み無効遡り範囲[E]\r
+       \r
+       private String adate;                                   // 開始日[T]\r
+       private String zdate;                                   // 終了日[T]\r
+       \r
+       private ArrayList<String> chNames = new ArrayList<String>();                            // チャンネル名 ※CHコード:[E]予約操作時と同じ、[T]コントローラの値と同じ(ただしこちらはHEX表記)\r
+       private ArrayList<ProgSubgenre> subgenres = new ArrayList<ProgSubgenre>();      // ジャンル\r
+       private ArrayList<ProgOption> options =  new ArrayList<ProgOption>();           // 番組属性 ※[E]無料/有料のみ\r
+       \r
+       private ReserveInfo recSetting;                         // 録画設定\r
 \r
        \r
        /*******************************************************************************\r
         * getter/setter\r
         ******************************************************************************/\r
        \r
-       public String getId() { return Id; }\r
-       public void setId(String s) { Id = s; }\r
+       public String getId() { return id; }\r
+       public void setId(String s) { id = s; }\r
        \r
-       public String getLabel() { return Label; }\r
-       public void setLabel(String s) { Label = s; }\r
+       public String getLabel() { return label; }\r
+       public void setLabel(String s) { label = s; }\r
 \r
-       public String getIncludeKeyword() { return IncludeKeyword; }\r
-       public void setIncludeKeyword(String s) { IncludeKeyword = s; }\r
-       public String getExcludeKeyword() { return ExcludeKeyword; }\r
-       public void setExcludeKeyword(String s) { ExcludeKeyword = s; }\r
+       public String getKeyword() { return keyword; }\r
+       public void setKeyword(String s) { keyword = s; }\r
+       public String getExKeyword() { return exKeyword; }\r
+       public void setExKeyword(String s) { exKeyword = s; }\r
 \r
-       public Boolean getRegularExpression() { return RegularExpression; }\r
-       public void setRegularExpression(Boolean b) { RegularExpression = b; }\r
-       public Boolean getFazzySearch() { return FazzySearch; }\r
-       public void setFazzySearch(Boolean b) { FazzySearch = b; }\r
-       public Boolean getTitleOnly() { return TitleOnly; }\r
-       public void setTitleOnly(Boolean b) { TitleOnly = b; }\r
+       public boolean getRegularExpression() { return regularExpression; }\r
+       public void setRegularExpression(boolean b) { regularExpression = b; }\r
+       public boolean getFazzySearch() { return fazzySearch; }\r
+       public void setFazzySearch(boolean b) { fazzySearch = b; }\r
+       public boolean getTitleOnly() { return titleOnly; }\r
+       public void setTitleOnly(boolean b) { titleOnly = b; }\r
        \r
-       public ArrayList<String> getChannels() { return Channels; }\r
+       public boolean getUniqTimeslot() { return uniqTimeslot; }\r
+       public void setUniqTimeslot(boolean b) { uniqTimeslot = b; }\r
+       \r
+       public int getRecordedCheckTerm() { return recordedCheckTerm; }\r
+       public void setRecordedCheckTerm(int n) { recordedCheckTerm = n; }\r
+       \r
+       /**\r
+        * 使用しない曜日の場合はnullを代入する\r
+        */\r
+       public ArrayList<String> getTimeslots() { return timeslots; }\r
+       public ArrayList<String> getChannels() { return chNames; }\r
+       \r
+       public ReserveInfo getRecSetting() { return recSetting; }\r
+       public void setRecSetting(ReserveInfo r) { recSetting = r; } \r
        \r
        /*******************************************************************************\r
         * extra\r
         ******************************************************************************/\r
        \r
-       public String getChNames() { return (Channels.size() > 0) ? Channels.get(0) : null; }\r
+       public String getChNames() { return (chNames.size() > 0) ? chNames.get(0) : null; }\r
+\r
 \r
 }\r
index b00a546..b72f87d 100644 (file)
@@ -8,11 +8,82 @@ public class AutoReserveInfoList extends ArrayList<AutoReserveInfo> {
 \r
        private static final long serialVersionUID = 1L;\r
        \r
-       private final String filename;\r
+       /*******************************************************************************\r
+        * 定数\r
+        ******************************************************************************/\r
        \r
-       public AutoReserveInfoList(String envdir, String recid, String ipaddr, String portno) {\r
+       private static final String BASENAME = "autorsv";       // basenameを指定しなかった場合のデフォルト値\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * 部品\r
+        ******************************************************************************/\r
+       \r
+       private final String envXml;\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * getter/setter\r
+        ******************************************************************************/\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * コンストラクタ\r
+        ******************************************************************************/\r
+       \r
+       /**\r
+        * シリアライズ用のデフォルトコンストラクタ\r
+        */\r
+       @Deprecated\r
+       public AutoReserveInfoList() {\r
                super();\r
-               this.filename = String.format("%s%s%s.%s_%s_%s.txt", "env", File.separator, "autorsv", recid, ipaddr, portno);\r
+               envXml = null;\r
+       }\r
+       \r
+       /**\r
+        * コンストラクタ\r
+        * @param basename null値は指定してした場合は{@link #BASENAME}が使用される\r
+        */\r
+       public AutoReserveInfoList(String envdir, String basename, String recid, String ipaddr, String portno) {\r
+               super();\r
+               this.envXml = String.format("%s%s%s.%s_%s_%s.xml", envdir, File.separator, ((basename==null)?BASENAME:basename), recid, ipaddr, portno);\r
        }\r
 \r
+       /*******************************************************************************\r
+        * 操作系メソッド\r
+        ******************************************************************************/\r
+       \r
+       public boolean exists() {\r
+               if (envXml == null ) {\r
+                       return false;\r
+               }\r
+               return new File(envXml).exists();\r
+       }\r
+       \r
+       /*******************************************************************************\r
+        * シリアライズ・デシリアライズ\r
+        ******************************************************************************/\r
+       \r
+       /**\r
+        * テキスト形式で保存する\r
+        */\r
+       public boolean save() {\r
+               if ( envXml == null ) {\r
+                       return false;\r
+               }\r
+               \r
+               return CommonUtils.writeXML(envXml, this);\r
+       }\r
+       \r
+       /**\r
+        * テキスト形式で読み込む\r
+        */\r
+       public boolean load() {\r
+               if ( envXml == null ) {\r
+                       return false;\r
+               }\r
+               \r
+               return CommonUtils.readXML(envXml, this);\r
+       }\r
+       \r
 }\r
index e71b085..2c54242 100644 (file)
@@ -202,7 +202,7 @@ public class Bounds {
        public void setFrameBufferSize(int n) { frameBufferSize = n; }\r
        \r
        //\r
-       private boolean loaded;\r
+       private static boolean loaded;\r
        public boolean isLoaded() { return loaded; }\r
        public void setLoaded(boolean b) { loaded = b; }\r
        \r
@@ -236,7 +236,7 @@ public class Bounds {
                        if ( b != null ) {\r
                                b.setListedColumnWidth(b.getListedColumnWidth());       // 旧型式→新形式に変換\r
                                b.setRsvedColumnWidth(b.getRsvedColumnWidth());         // 旧型式→新形式に変換\r
-                               CommonUtils.FieldCopy(this, b);\r
+                               FieldUtils.deepCopy(this, b);\r
                                \r
                                // テキスト形式がなければ作るよ\r
                                if ( FieldUtils.save(BOUNDS_TEXT,this) ) {\r
index 7a9e95b..ba4a2a5 100644 (file)
@@ -257,7 +257,7 @@ public class ChannelCode extends ArrayList<String> implements Cloneable {
        @Override\r
        public ChannelCode clone() {\r
                ChannelCode cc = (ChannelCode) super.clone();\r
-               CommonUtils.FieldCopy(cc, this); // ディープコピーするよ\r
+               FieldUtils.deepCopy(cc, this); // ディープコピーするよ\r
                return cc;\r
        }\r
 }\r
index e5ffa5d..aaed187 100644 (file)
@@ -41,7 +41,7 @@ public class ClipboardInfoList extends ArrayList<ClipboardInfo> {
                                ArrayList<clipboardItem> clx = (ArrayList<clipboardItem>) CommonUtils.readXML(cbFileOld);\r
                                for ( clipboardItem cx : clx ) {\r
                                        ClipboardInfo c = new ClipboardInfo();\r
-                                       CommonUtils.FieldCopy(c, cx);\r
+                                       FieldUtils.deepCopy(c, cx);\r
                                        cl.add(c);\r
                                }\r
                        }\r
index b856833..bbd41a7 100644 (file)
@@ -2,7 +2,6 @@
 package tainavi;\r
 \r
 import java.awt.Color;\r
-import java.awt.Component;\r
 import java.awt.Desktop;\r
 import java.beans.XMLDecoder;\r
 import java.beans.XMLEncoder;\r
@@ -23,21 +22,13 @@ import java.io.OutputStream;
 import java.io.OutputStreamWriter;\r
 import java.io.Reader;\r
 import java.io.Writer;\r
-import java.lang.reflect.Array;\r
-import java.lang.reflect.Field;\r
-import java.lang.reflect.InvocationTargetException;\r
-import java.lang.reflect.Method;\r
-import java.lang.reflect.Modifier;\r
 import java.net.HttpURLConnection;\r
 import java.net.Socket;\r
 import java.nio.channels.FileChannel;\r
 import java.nio.channels.FileLock;\r
 import java.text.SimpleDateFormat;\r
-import java.util.AbstractList;\r
-import java.util.AbstractMap;\r
 import java.util.ArrayList;\r
 import java.util.Calendar;\r
-import java.util.ConcurrentModificationException;\r
 import java.util.GregorianCalendar;\r
 import java.util.HashMap;\r
 import java.util.Map.Entry;\r
@@ -947,287 +938,6 @@ public class CommonUtils {
         * オブジェクト操作関連\r
         ******************************************************************************/\r
 \r
-       /**\r
-        * <P>オブジェクトからオブジェクトへフィールドのコピー(ディープコピー)を行います。\r
-        * <P>新しく作ったインスタンスに入れ替えたいけど、ポインタを変えたくないので中身だけコピーできないか?という時に使います。\r
-        * <P>fromにあってtoにないフィールドについては無視して最後まで処理を続行します(というか型違いとかも無視します)。\r
-        * <P>多分遅いので、設定ファイルの読み出しなど使用頻度の少ないところで利用します。\r
-        * @param to : HashMapクラスの場合は、コピー先にインスタンスが存在している必要があります(nullはだめ)\r
-        * @param from\r
-        * @version 3.15.4β~\r
-        */\r
-       public static boolean FieldCopy(final Object to, final Object from) {\r
-               try {\r
-                       return FieldCopy(to,from,null);\r
-               }\r
-               catch (Exception e) {\r
-                       e.printStackTrace();\r
-               }\r
-               return false;\r
-       }\r
-       \r
-       @SuppressWarnings("rawtypes")\r
-       private static boolean FieldCopy(final Object to, final Object from, final Field fn) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ConcurrentModificationException, InstantiationException  {\r
-               \r
-               // 継承しているクラスのリストを作成する\r
-               ArrayList<Class> fromCL = new ArrayList<Class>();\r
-               ArrayList<Class> toCL = new ArrayList<Class>();\r
-               for ( Class c=from.getClass(); c!=null && ! Object.class.equals(c); c=c.getSuperclass() ) {\r
-                       //if (debug) System.out.println("[DEBUG] FROM "+c.getName());\r
-                       fromCL.add(c);\r
-               }\r
-               for ( Class c=to.getClass(); c!=null && ! Object.class.equals(c); c=c.getSuperclass() ) {\r
-                       //if (debug) System.out.println("[DEBUG] TO "+c.getName());\r
-                       toCL.add(c);\r
-               }\r
-\r
-               // 両方の開始位置をそろえる\r
-               while ( fromCL.size() > 0 && ! toCL.contains(fromCL.get(0)) ) {\r
-                       if (debuglv2) System.out.println("[DEBUG] removed FROM "+fromCL.get(0).getName());\r
-                       fromCL.remove(0);\r
-               }\r
-               while ( toCL.size() > 0 && ! fromCL.contains(toCL.get(0)) ) {\r
-                       if (debuglv2) System.out.println("[DEBUG] removed TO "+toCL.get(0).getName());\r
-                       toCL.remove(0);\r
-               }\r
-               \r
-               int i=0;\r
-               for ( Class c : fromCL ) {\r
-                       \r
-                       i++;\r
-                       \r
-                       String ctype = (i>1)?(" (super class)"):("");\r
-                       String cname = c.getName();\r
-                       String fname = (fn!=null)?(" name="+fn.getName()):("");\r
-                       \r
-                       if ( isHashMap(to,from,c,fn) ) {\r
-                               if (debuglv2) System.err.println("[DEBUG] FieldCopy("+cname+") *** TERM *** deep copy"+ctype+fname);\r
-                               return true;\r
-                       }\r
-                       \r
-                       if ( isLeaf(to,from,c,fn) ) {\r
-                               if (debuglv2) System.err.println("[DEBUG] FieldCopy("+cname+") *** TERM *** leaf"+ctype+fname);\r
-                               return true;\r
-                       }\r
-                       \r
-                       Field[] fd = c.getDeclaredFields();\r
-                       \r
-                       // フィールドなんかねーよ\r
-                       if ( fd.length == 0 ) {\r
-                               if ( fn == null ) {\r
-                                       // 継承だけして追加のフィールドがない場合にここに入る\r
-                                       if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") no field"+ctype+fname);\r
-                                       continue;\r
-                               }\r
-                               \r
-                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") *** TERM *** no field"+ctype+fname);\r
-                               return isCopyable(to,from,c,fn);        // 終端\r
-                       }\r
-                       \r
-                       // (フィールド)たんけんぼくのまち。チョーさん生きてるよ!\r
-                       for ( Field f : fd ) {\r
-                               f.setAccessible(true);\r
-                               \r
-                               String xcname = f.getType().getName();\r
-                               String xfname = " name="+f.getName();\r
-                               \r
-                               int mod = f.getModifiers();\r
-                               \r
-                               if ( Modifier.isFinal(mod) ) {\r
-                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+xcname+") : FINAL field "+ctype+xfname);\r
-                                       continue;\r
-                               }\r
-                               if ( Modifier.isStatic(mod) ) {\r
-                                       if (debug) System.err.println("[DEBUG] FieldCopy("+xcname+") : STATIC field "+ctype+xfname);\r
-                                       continue;\r
-                               }\r
-                               \r
-                               \r
-                               Object o = f.get(from);\r
-                               if ( o == null ) {\r
-                                       if (debug) System.err.println("[DEBUG] FieldCopy("+xcname+") *** TERM *** null value FROM"+ctype+xfname);\r
-                                       f.set(to, null);\r
-                                       continue;       // 終端\r
-                               }\r
-                               \r
-                               Class xc = o.getClass();\r
-                               xcname = xc.getName();\r
-                               \r
-                               if ( isHashMap(to,o,xc,f) ) {\r
-                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+xcname+") *** TERM *** deep copy"+ctype+xfname);\r
-                                       continue;\r
-                               }\r
-                               \r
-                               if ( isLeaf(to,o,xc,f) ) {\r
-                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+xcname+") *** TERM *** leaf"+ctype+xfname);\r
-                                       continue;\r
-                               }\r
-                               \r
-                               isCopyable(to,o,xc,f);  // 終端\r
-                       }\r
-               }\r
-               \r
-               return true;\r
-       }\r
-       \r
-       // HashMapとか、コピーする\r
-       @SuppressWarnings({ "unchecked", "rawtypes" })\r
-       private static boolean isHashMap(Object to, Object from, Class c, Field f) throws InstantiationException, IllegalAccessException, ConcurrentModificationException  {\r
-               \r
-               String cname = c.getName();\r
-               String fname = " name="+((f==null)?("<TOP>"):(f.getName()));\r
-               \r
-               for ( Class cx : unCloneables ) {\r
-                       if ( cx.equals(c) ) {\r
-                               if ( HashMap.class.equals(c) || ArrayList.class.equals(c) ) {\r
-               \r
-                                       final Object px = (f==null)?(to):(f.get(to));\r
-                                       if ( px == null ) {\r
-                                               // コピー先にインスタンスが存在している必要がある\r
-                                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isCloneable() : must have been initialized"+fname);\r
-                                               return true;\r
-                                       }\r
-                                       \r
-                                       // 個別(キャスト!)\r
-               \r
-                                       if ( HashMap.class.equals(c) ) {\r
-                                               HashMap<Object, Object> o = (HashMap<Object, Object>) from;\r
-                                               HashMap<Object, Object> p;\r
-                                               if ( f != null ) {\r
-                                                       // フィールドならclone()では社ローコピーのせいで同じものを指してるに違いない、新しいインスタンスを作らないといけない\r
-                                                       p = (HashMap<Object, Object>) c.newInstance();\r
-                                               }\r
-                                               else {\r
-                                                       // 自身(orスーパークラス)なら別物だろうからキャストで大丈夫だろう\r
-                                                       p = (HashMap<Object, Object>) to;\r
-                                               }\r
-                                               \r
-                                               p.clear(); // とりあえず消す\r
-                                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isHashMap() : HashMap "+cname+fname+" size="+o.size());\r
-                                               for ( Entry<Object, Object> entry: o.entrySet() ) {\r
-                                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+cname+") / isHashMap() : copy"+fname+" key="+entry.getKey()+" value="+entry.getValue());\r
-                                                       p.put(entry.getKey(), entry.getValue());\r
-                                               }\r
-                                               \r
-                                               if ( f != null ) {\r
-                                                       f.set(to, p);\r
-                                               }\r
-                                       }\r
-                                       else if ( ArrayList.class.equals(c) ) {\r
-                                               ArrayList<Object> o = (ArrayList<Object>) from;\r
-                                               ArrayList<Object> p = null;\r
-                                               if ( f != null ) {\r
-                                                       p = (ArrayList<Object>) c.newInstance();\r
-                                               }\r
-                                               else {\r
-                                                       p = (ArrayList<Object>) to;\r
-                                               }\r
-                                               \r
-                                               p.clear(); // とりあえず消す\r
-                                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isHashMap() : ArrayList "+cname+fname+" size="+o.size());\r
-                                               for ( Object entry: o ) {\r
-                                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+cname+") / isHashMap() : copy"+fname+" value="+entry);\r
-                                                       p.add(entry);\r
-                                               }\r
-                                               \r
-                                               if ( f != null ) {\r
-                                                       f.set(to, p);\r
-                                               }\r
-                                       }\r
-                               }\r
-                               else {\r
-                                       if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isHashMap() : unsupported"+fname);\r
-                               }\r
-                               return true;\r
-                       }                       \r
-               }\r
-               return false;\r
-       }\r
-       \r
-       @SuppressWarnings("rawtypes")\r
-       private static final Class[] unCloneables = { HashMap.class, AbstractMap.class, ArrayList.class, AbstractList.class };\r
-       \r
-       // Integerとか、コピーする\r
-       @SuppressWarnings("rawtypes")\r
-       private static boolean isLeaf(Object to, Object from, Class c, Field f) throws IllegalArgumentException, IllegalAccessException {\r
-               \r
-               String cname = c.getName();\r
-               String fname = " name="+((f==null)?("<TOP>"):(f.getName()));\r
-               \r
-               if ( from instanceof String || from instanceof Boolean || from instanceof Number || from instanceof Color || from instanceof Enum || from instanceof Component ) {\r
-                       if ( f == null ) {\r
-                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isLeaf() : <Top> is not allowed");\r
-                               return true;\r
-                       }\r
-                               \r
-                       //if (debuglv2) System.err.println("[DEBUG] FieldCopy("+cname+") / isLeaf() : leaf field"+fname);\r
-                       f.set(to, from);\r
-                       return true;\r
-               }\r
-               \r
-               return false;\r
-       }\r
-       \r
-       //\r
-       @SuppressWarnings("rawtypes")\r
-       private static boolean isCopyable(Object to, Object from, Class c, Field f) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException {\r
-               \r
-               String cname = c.getName();\r
-               String fname = " name="+((f==null)?("<TOP>"):(f.getName()));\r
-               \r
-               // コピーに失敗して例外の発生したフィールドについては無視します\r
-               \r
-               if ( c.isPrimitive() ) {\r
-                       if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isCopyable() : primitive"+fname);\r
-                       f.set(to, from);\r
-               }\r
-               else if ( c.isArray() ) {\r
-                       if ( f == null ) {\r
-                               // 自分自身だとコピーするしかないが、しない。redim()があればなんとかできたのに!\r
-                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isCopyable() : not copyable array"+fname);\r
-                       }\r
-                       else {\r
-                               // フィールドなら入れ物は作る。要素はコピー\r
-                               Class comp = c.getComponentType();\r
-                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isCopyable() : array of "+comp.getName()+fname+" lenth="+Array.getLength(from));\r
-                               Object[] o = (Object[]) from;\r
-                               Object[] p = (Object[]) Array.newInstance(comp, Array.getLength(from));\r
-                               \r
-                               for ( int i=o.length-1; i>=0; i-- ) {\r
-                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+comp.getName()+") / isCopyable() : copy"+fname+" value="+o[i]);\r
-                                       p[i] = o[i];\r
-                               }\r
-                       }\r
-               }\r
-               else {\r
-                       // そのほかは可能な限りcloneする\r
-                       invokeClone(to,from,c,f);\r
-               }\r
-               \r
-               return true;\r
-       }\r
-       \r
-       //\r
-       @SuppressWarnings("rawtypes")\r
-       private static boolean invokeClone(Object to, Object from, Class c, Field f) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {\r
-               \r
-               final String cname = c.getName();\r
-               final String fname = " name="+((f==null)?("<TOP>"):(f.getName())); // よく考えたらここにf==nullで入ってくることはない\r
-               \r
-               try {\r
-                       @SuppressWarnings("unchecked")\r
-                       Method m = c.getMethod("clone");\r
-                       f.set(to, m.invoke(from));\r
-                       if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / invokeClone() : invoke clone "+cname+fname);\r
-                       return true;\r
-               }\r
-               catch (NoSuchMethodException e) {\r
-                       // ちょっとこわいのでコピーせずに無視\r
-                       if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / invokeClone() : clone unsupported and ignored "+fname);\r
-               }\r
-               return false;\r
-       }\r
-       \r
        /*******************************************************************************\r
         * JavaVM関連\r
         ******************************************************************************/\r
@@ -1789,7 +1499,7 @@ public class CommonUtils {
        }\r
        \r
        /**\r
-        *  XMLDecorderでシリアライズしたファイルを読みだす\r
+        * XMLDecorderでシリアライズしたファイルを読みだす(オブジェクトを返す場合)\r
         */\r
        public static Object readXML(String fname) {\r
                {\r
@@ -1815,6 +1525,19 @@ public class CommonUtils {
                return null;\r
        }\r
        \r
+       /**\r
+        * XMLDecorderでシリアライズしたファイルを読みだす(既存のオブジェクトに値を入れて返す場合)\r
+        */\r
+       public static boolean readXML(String fname, Object obj) {\r
+               \r
+               Object tmp = readXML(fname);\r
+               if ( tmp == null ) {\r
+                       return false;\r
+               }\r
+               \r
+               return FieldUtils.deepCopy(obj, tmp);\r
+       }\r
+\r
        /*\r
         * finallyブロックで書き間違えそうなので\r
         */\r
index d93f7f8..5e67821 100644 (file)
@@ -988,7 +988,7 @@ public class Env {
        if ( fx.exists() ) {\r
                Env b = (Env) CommonUtils.readXML(envFile);\r
                if ( b != null ) {\r
-                       CommonUtils.FieldCopy(this, b);\r
+                       FieldUtils.deepCopy(this, b);\r
                        \r
                                // テキスト形式がなければ作るよ\r
                                if ( FieldUtils.save(envText,this) ) {\r
index 348161a..b326873 100644 (file)
@@ -1,12 +1,19 @@
 package tainavi;\r
 \r
 import java.awt.Color;\r
+import java.awt.Component;\r
 import java.awt.Rectangle;\r
 import java.io.File;\r
+import java.lang.reflect.Array;\r
 import java.lang.reflect.Field;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
 import java.lang.reflect.Modifier;\r
 import java.lang.reflect.ParameterizedType;\r
+import java.util.AbstractList;\r
+import java.util.AbstractMap;\r
 import java.util.ArrayList;\r
+import java.util.ConcurrentModificationException;\r
 import java.util.HashMap;\r
 import java.util.Map.Entry;\r
 import java.util.regex.Pattern;\r
@@ -19,7 +26,17 @@ import tainavi.JTXTButton.FontStyle;
 import tainavi.TVProgram.ProgOption;\r
 \r
 \r
+/**\r
+ * オブジェクトのフィールドを操作するユーティリティーメソッド群\r
+ * \r
+ * @version 3.22.2b CommonUtils#FieldCopy()を{@link #deepCopy(Object, Object)}に移動<BR>\r
+ */\r
 public class FieldUtils {\r
+\r
+       public void setDebug(boolean b) { debug = b; }\r
+       private static boolean debug = false;\r
+       \r
+       private static boolean debuglv2 = false;\r
        \r
        /*******************************************************************************\r
         * 定数とか\r
@@ -38,6 +55,8 @@ public class FieldUtils {
        private static final String SPHD_UNS = SPMK_CM+" UNSUPPORTED : ";\r
        private static final String SPHD_NOE = SPMK_CM+" NOELEMENT : ";\r
        \r
+       private static final String CMNT_AS = " AS ";\r
+       \r
        private static final String MSGID = "[設定保存] ";\r
        private static final String ERRID = "[ERROR]"+MSGID;\r
        \r
@@ -77,7 +96,7 @@ public class FieldUtils {
                                if ( fx.getAnnotation(Deprecated.class) != null ) {\r
                                        sb.append(SPHD_DEP);\r
                                        sb.append(key);\r
-                                       sb.append(" AS ");\r
+                                       sb.append(CMNT_AS);\r
                                        sb.append(cls.getName());\r
                                        sb.append(SPMK_LF);\r
                                        continue;\r
@@ -146,7 +165,7 @@ public class FieldUtils {
                                                                sb.append("]");\r
                                                                n++;\r
                                                        }\r
-                                                       sb.append(" AS ");\r
+                                                       sb.append(CMNT_AS);\r
                                                        sb.append(ocls.getName());\r
                                                        sb.append(SPMK_LF);\r
                                                }\r
@@ -490,4 +509,291 @@ public class FieldUtils {
                throw new UnsupportedOperationException("未対応の項目");\r
        }\r
 \r
+       \r
+       \r
+       /*******************************************************************************\r
+        * ディープコピーする\r
+        ******************************************************************************/\r
+       \r
+       /**\r
+        * <P>オブジェクトからオブジェクトへフィールドのコピー(ディープコピー)を行います。\r
+        * <P>新しく作ったインスタンスに入れ替えたいけど、ポインタを変えたくないので中身だけコピーできないか?という時に使います。\r
+        * <P>fromにあってtoにないフィールドについては無視して最後まで処理を続行します(というか型違いとかも無視します)。\r
+        * <P>多分遅いので、設定ファイルの読み出しなど使用頻度の少ないところで利用します。\r
+        * <P>final修飾、static修飾のある変数はコピーされません\r
+        * @param to : HashMapクラス、ArrayListクラスの場合は、コピー先にインスタンスが存在している必要があります(nullはだめ)\r
+        * @param from\r
+        * @version 3.15.4β~\r
+        */\r
+       public static boolean deepCopy(final Object to, final Object from) {\r
+               try {\r
+                       return FieldCopy(to,from,null);\r
+               }\r
+               catch (Exception e) {\r
+                       e.printStackTrace();\r
+               }\r
+               return false;\r
+       }\r
+       \r
+       @SuppressWarnings("rawtypes")\r
+       private static boolean FieldCopy(final Object to, final Object from, final Field fn) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ConcurrentModificationException, InstantiationException  {\r
+               \r
+               // 継承しているクラスのリストを作成する\r
+               ArrayList<Class> fromCL = new ArrayList<Class>();\r
+               ArrayList<Class> toCL = new ArrayList<Class>();\r
+               for ( Class c=from.getClass(); c!=null && ! Object.class.equals(c); c=c.getSuperclass() ) {\r
+                       //if (debug) System.out.println("[DEBUG] FROM "+c.getName());\r
+                       fromCL.add(c);\r
+               }\r
+               for ( Class c=to.getClass(); c!=null && ! Object.class.equals(c); c=c.getSuperclass() ) {\r
+                       //if (debug) System.out.println("[DEBUG] TO "+c.getName());\r
+                       toCL.add(c);\r
+               }\r
+\r
+               // 両方の開始位置をそろえる\r
+               while ( fromCL.size() > 0 && ! toCL.contains(fromCL.get(0)) ) {\r
+                       if (debuglv2) System.out.println("[DEBUG] removed FROM "+fromCL.get(0).getName());\r
+                       fromCL.remove(0);\r
+               }\r
+               while ( toCL.size() > 0 && ! fromCL.contains(toCL.get(0)) ) {\r
+                       if (debuglv2) System.out.println("[DEBUG] removed TO "+toCL.get(0).getName());\r
+                       toCL.remove(0);\r
+               }\r
+               \r
+               int i=0;\r
+               for ( Class c : fromCL ) {\r
+                       \r
+                       i++;\r
+                       \r
+                       String ctype = (i>1)?(" (super class)"):("");\r
+                       String cname = c.getName();\r
+                       String fname = (fn!=null)?(" name="+fn.getName()):("");\r
+                       \r
+                       if ( isHashMap(to,from,c,fn) ) {\r
+                               if (debuglv2) System.err.println("[DEBUG] FieldCopy("+cname+") *** TERM *** deep copy"+ctype+fname);\r
+                               return true;\r
+                       }\r
+                       \r
+                       if ( isLeaf(to,from,c,fn) ) {\r
+                               if (debuglv2) System.err.println("[DEBUG] FieldCopy("+cname+") *** TERM *** leaf"+ctype+fname);\r
+                               return true;\r
+                       }\r
+                       \r
+                       Field[] fd = c.getDeclaredFields();\r
+                       \r
+                       // フィールドなんかねーよ\r
+                       if ( fd.length == 0 ) {\r
+                               if ( fn == null ) {\r
+                                       // 継承だけして追加のフィールドがない場合にここに入る\r
+                                       if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") no field"+ctype+fname);\r
+                                       continue;\r
+                               }\r
+                               \r
+                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") *** TERM *** no field"+ctype+fname);\r
+                               return isCopyable(to,from,c,fn);        // 終端\r
+                       }\r
+                       \r
+                       // (フィールド)たんけんぼくのまち。チョーさん生きてるよ!\r
+                       for ( Field f : fd ) {\r
+                               f.setAccessible(true);\r
+                               \r
+                               String xcname = f.getType().getName();\r
+                               String xfname = " name="+f.getName();\r
+                               \r
+                               int mod = f.getModifiers();\r
+                               \r
+                               if ( Modifier.isFinal(mod) ) {\r
+                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+xcname+") : FINAL field "+ctype+xfname);\r
+                                       continue;\r
+                               }\r
+                               if ( Modifier.isStatic(mod) ) {\r
+                                       if (debug) System.err.println("[DEBUG] FieldCopy("+xcname+") : STATIC field "+ctype+xfname);\r
+                                       continue;\r
+                               }\r
+                               \r
+                               \r
+                               Object o = f.get(from);\r
+                               if ( o == null ) {\r
+                                       if (debug) System.err.println("[DEBUG] FieldCopy("+xcname+") *** TERM *** null value FROM"+ctype+xfname);\r
+                                       f.set(to, null);\r
+                                       continue;       // 終端\r
+                               }\r
+                               \r
+                               Class xc = o.getClass();\r
+                               xcname = xc.getName();\r
+                               \r
+                               if ( isHashMap(to,o,xc,f) ) {\r
+                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+xcname+") *** TERM *** deep copy"+ctype+xfname);\r
+                                       continue;\r
+                               }\r
+                               \r
+                               if ( isLeaf(to,o,xc,f) ) {\r
+                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+xcname+") *** TERM *** leaf"+ctype+xfname);\r
+                                       continue;\r
+                               }\r
+                               \r
+                               isCopyable(to,o,xc,f);  // 終端\r
+                       }\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       // HashMapとか、コピーする\r
+       @SuppressWarnings({ "unchecked", "rawtypes" })\r
+       private static boolean isHashMap(Object to, Object from, Class c, Field f) throws InstantiationException, IllegalAccessException, ConcurrentModificationException  {\r
+               \r
+               String cname = c.getName();\r
+               String fname = " name="+((f==null)?("<TOP>"):(f.getName()));\r
+               \r
+               for ( Class cx : unCloneables ) {\r
+                       if ( cx.equals(c) ) {\r
+                               if ( HashMap.class.equals(c) || ArrayList.class.equals(c) ) {\r
+               \r
+                                       final Object px = (f==null)?(to):(f.get(to));\r
+                                       if ( px == null ) {\r
+                                               // コピー先にインスタンスが存在している必要がある\r
+                                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isCloneable() : must have been initialized"+fname);\r
+                                               return true;\r
+                                       }\r
+                                       \r
+                                       // 個別(キャスト!)\r
+               \r
+                                       if ( HashMap.class.equals(c) ) {\r
+                                               HashMap<Object, Object> o = (HashMap<Object, Object>) from;\r
+                                               HashMap<Object, Object> p;\r
+                                               if ( f != null ) {\r
+                                                       // フィールドならclone()では社ローコピーのせいで同じものを指してるに違いない、新しいインスタンスを作らないといけない\r
+                                                       p = (HashMap<Object, Object>) c.newInstance();\r
+                                               }\r
+                                               else {\r
+                                                       // 自身(orスーパークラス)なら別物だろうからキャストで大丈夫だろう\r
+                                                       p = (HashMap<Object, Object>) to;\r
+                                               }\r
+                                               \r
+                                               p.clear(); // とりあえず消す\r
+                                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isHashMap() : HashMap "+cname+fname+" size="+o.size());\r
+                                               for ( Entry<Object, Object> entry: o.entrySet() ) {\r
+                                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+cname+") / isHashMap() : copy"+fname+" key="+entry.getKey()+" value="+entry.getValue());\r
+                                                       p.put(entry.getKey(), entry.getValue());\r
+                                               }\r
+                                               \r
+                                               if ( f != null ) {\r
+                                                       f.set(to, p);\r
+                                               }\r
+                                       }\r
+                                       else if ( ArrayList.class.equals(c) ) {\r
+                                               ArrayList<Object> o = (ArrayList<Object>) from;\r
+                                               ArrayList<Object> p = null;\r
+                                               if ( f != null ) {\r
+                                                       p = (ArrayList<Object>) c.newInstance();\r
+                                               }\r
+                                               else {\r
+                                                       p = (ArrayList<Object>) to;\r
+                                               }\r
+                                               \r
+                                               p.clear(); // とりあえず消す\r
+                                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isHashMap() : ArrayList "+cname+fname+" size="+o.size());\r
+                                               for ( Object entry: o ) {\r
+                                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+cname+") / isHashMap() : copy"+fname+" value="+entry);\r
+                                                       p.add(entry);\r
+                                               }\r
+                                               \r
+                                               if ( f != null ) {\r
+                                                       f.set(to, p);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               else {\r
+                                       if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isHashMap() : unsupported"+fname);\r
+                               }\r
+                               return true;\r
+                       }                       \r
+               }\r
+               return false;\r
+       }\r
+       \r
+       @SuppressWarnings("rawtypes")\r
+       private static final Class[] unCloneables = { HashMap.class, AbstractMap.class, ArrayList.class, AbstractList.class };\r
+       \r
+       // Integerとか、コピーする\r
+       @SuppressWarnings("rawtypes")\r
+       private static boolean isLeaf(Object to, Object from, Class c, Field f) throws IllegalArgumentException, IllegalAccessException {\r
+               \r
+               String cname = c.getName();\r
+               //String fname = " name="+((f==null)?("<TOP>"):(f.getName()));\r
+               \r
+               if ( from instanceof String || from instanceof Boolean || from instanceof Number || from instanceof Color || from instanceof Enum || from instanceof Component ) {\r
+                       if ( f == null ) {\r
+                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isLeaf() : <Top> is not allowed");\r
+                               return true;\r
+                       }\r
+                               \r
+                       //if (debuglv2) System.err.println("[DEBUG] FieldCopy("+cname+") / isLeaf() : leaf field"+fname);\r
+                       f.set(to, from);\r
+                       return true;\r
+               }\r
+               \r
+               return false;\r
+       }\r
+       \r
+       //\r
+       @SuppressWarnings("rawtypes")\r
+       private static boolean isCopyable(Object to, Object from, Class c, Field f) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException {\r
+               \r
+               String cname = c.getName();\r
+               String fname = " name="+((f==null)?("<TOP>"):(f.getName()));\r
+               \r
+               // コピーに失敗して例外の発生したフィールドについては無視します\r
+               \r
+               if ( c.isPrimitive() ) {\r
+                       if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isCopyable() : primitive"+fname);\r
+                       f.set(to, from);\r
+               }\r
+               else if ( c.isArray() ) {\r
+                       if ( f == null ) {\r
+                               // 自分自身だとコピーするしかないが、しない。redim()があればなんとかできたのに!\r
+                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isCopyable() : not copyable array"+fname);\r
+                       }\r
+                       else {\r
+                               // フィールドなら入れ物は作る。要素はコピー\r
+                               Class comp = c.getComponentType();\r
+                               if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / isCopyable() : array of "+comp.getName()+fname+" lenth="+Array.getLength(from));\r
+                               Object[] o = (Object[]) from;\r
+                               Object[] p = (Object[]) Array.newInstance(comp, Array.getLength(from));\r
+                               \r
+                               for ( int i=o.length-1; i>=0; i-- ) {\r
+                                       if (debuglv2) System.err.println("[DEBUG] FieldCopy("+comp.getName()+") / isCopyable() : copy"+fname+" value="+o[i]);\r
+                                       p[i] = o[i];\r
+                               }\r
+                       }\r
+               }\r
+               else {\r
+                       // そのほかは可能な限りcloneする\r
+                       invokeClone(to,from,c,f);\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       //\r
+       @SuppressWarnings("rawtypes")\r
+       private static boolean invokeClone(Object to, Object from, Class c, Field f) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {\r
+               \r
+               final String cname = c.getName();\r
+               final String fname = " name="+((f==null)?("<TOP>"):(f.getName())); // よく考えたらここにf==nullで入ってくることはない\r
+               \r
+               try {\r
+                       @SuppressWarnings("unchecked")\r
+                       Method m = c.getMethod("clone");\r
+                       f.set(to, m.invoke(from));\r
+                       if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / invokeClone() : invoke clone "+cname+fname);\r
+                       return true;\r
+               }\r
+               catch (NoSuchMethodException e) {\r
+                       // ちょっとこわいのでコピーせずに無視\r
+                       if (debug) System.err.println("[DEBUG] FieldCopy("+cname+") / invokeClone() : clone unsupported and ignored "+fname);\r
+               }\r
+               return false;\r
+       }\r
 }\r
diff --git a/TinyBannavi/src/tainavi/FieldUtils2.java b/TinyBannavi/src/tainavi/FieldUtils2.java
new file mode 100644 (file)
index 0000000..09ded06
--- /dev/null
@@ -0,0 +1,793 @@
+package tainavi;\r
+\r
+import java.awt.Color;\r
+import java.awt.Component;\r
+import java.awt.Rectangle;\r
+import java.io.File;\r
+import java.lang.reflect.Array;\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Modifier;\r
+import java.lang.reflect.ParameterizedType;\r
+import java.lang.reflect.Type;\r
+import java.rmi.NoSuchObjectException;\r
+import java.util.AbstractList;\r
+import java.util.AbstractMap;\r
+import java.util.ArrayList;\r
+import java.util.ConcurrentModificationException;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.LinkedHashMap;\r
+import java.util.Map.Entry;\r
+import java.util.regex.Pattern;\r
+\r
+import tainavi.Env.AAMode;\r
+import tainavi.Env.DblClkCmd;\r
+import tainavi.Env.SnapshotFmt;\r
+import tainavi.Env.UpdateOn;\r
+import tainavi.JTXTButton.FontStyle;\r
+import tainavi.TVProgram.ProgOption;\r
+\r
+\r
+/**\r
+ * save()/load()は将来的にこちらに移行したい。 ※未完成 \r
+ */\r
+@Deprecated\r
+public class FieldUtils2 {\r
+       \r
+       public static void setDebug(boolean b) { debug = b; }\r
+       private static boolean debug = false;\r
+       \r
+       private static boolean debuglv2 = false;\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * 定数とか\r
+        ******************************************************************************/\r
+       \r
+       // 特殊値\r
+       private static final String SPCH_LF = "$LF$";           // 改行値\r
+       private static final String SPCH_NULL = "$NULL$";       // NULL値\r
+\r
+       // 記号類\r
+       private static final String SPMK_DOT = ".";                     // メンバ名の区切り文字\r
+       private static final String SPMK_CM = "#";                      // コメント行\r
+       private static final String SPMK_ALELM = "@";           // 配列のエレメントマーク\r
+       private static final String SPMK_HMELM_K = "%k";        // 連想配列のエレメントマーク\r
+       private static final String SPMK_HMELM_V = "%v";        // 連想配列のエレメントマーク\r
+       private static final String SPMK_SEP = "=";                     // key=value\r
+       private static final String SPMK_LF = "\n";                     // 改行文字\r
+       \r
+       // コメント\r
+       private static final String SPHD_MOD = SPMK_CM+" MODIFIED : ";          // 更新日時\r
+       private static final String SPHD_VER = SPMK_CM+" VERSION : ";           // 鯛ナビバージョン\r
+       private static final String SPHD_CLS = SPMK_CM+" CLASS : ";                     // ターゲットクラス\r
+       private static final String SPHD_DEP = SPMK_CM+" DEPRECATED : ";        // 廃止されている変数\r
+       //private static final String SPHD_UNSUP = SPMK_CM+" UNSUPPORTED : ";   // シリアライズできない変数\r
+       private static final String SPHD_UNSOL = SPMK_CM+" UNSOLVED : ";        // パラメータの型がわからない\r
+       private static final String SPHD_NOE = SPMK_CM+" NOELEMENT : ";         // エレメントを持たない配列・連想配列\r
+       //private static final String SPHD_FL  = SPMK_CM+" MY FIELDS ";         // ここからフィールドブロック\r
+       //private static final String SPHD_EL  = SPMK_CM+" MY ELEMENTS ";       // ここからエレメントブロック\r
+       \r
+       private static final String CMNT_AS = " AS ";\r
+       \r
+       // ログ関連\r
+       private static final String MSGID = "[設定保存] ";\r
+       private static final String ERRID = "[ERROR]"+MSGID;\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * シリアライズ\r
+        ******************************************************************************/\r
+\r
+       /**\r
+        * <P>自身がArrayList<T>やHashMap<K,V>やそのサブクラスだと、ジェネリクスのクラスが判定できないためシリアライズ不可。\r
+        * ArrayList<String>やHashMap<String,String>のサブクラスにしてやればOK。\r
+        * <P>final、static修飾子のあるフィールドには未対応。\r
+        * <P>自身のスーパークラスのフィールドにも未対応。\r
+        * <P>値がサブクラスだと正しくデシリアライズできない。\r
+        */\r
+       public static boolean save(String envText, Object root) {\r
+               \r
+               try {\r
+                       StringBuilder sb = new StringBuilder();\r
+                       \r
+                       // ヘッダ部\r
+                       sb.append(getHeader(root.getClass().getName()));\r
+                       \r
+                       // メンバ部\r
+                       String s = getBody("",root,root.getClass(),null);\r
+                       if ( s == null ) {\r
+                               return false;\r
+                       }\r
+                       sb.append(s);\r
+                       \r
+                       String text = sb.toString();\r
+                       \r
+                       if (debug) System.err.println(text);\r
+                       \r
+               System.out.println(MSGID+"テキスト形式で保存します: "+envText);\r
+               if ( ! CommonUtils.write2file(envText, text) ) {\r
+                       System.err.println(ERRID+"保存に失敗しました");\r
+                       return false;\r
+               }\r
+                       \r
+                       return true;\r
+               }\r
+               catch ( Exception e ) {\r
+                       // ジェネリックの扱いに失敗したとか\r
+                       e.printStackTrace();\r
+               }\r
+               \r
+               return false;\r
+       }\r
+       \r
+       public static String getHeader(String name) {\r
+               \r
+               StringBuilder sb = new StringBuilder();\r
+               \r
+               sb.append(SPHD_MOD);\r
+               sb.append(CommonUtils.getDateTime(0));\r
+               sb.append(SPMK_LF);\r
+               sb.append(SPHD_VER);\r
+               sb.append(VersionInfo.getVersionNumber());\r
+               sb.append(SPMK_LF);\r
+               sb.append(SPHD_CLS);\r
+               sb.append(name);\r
+               sb.append(SPMK_LF);\r
+               sb.append(SPMK_LF);\r
+               \r
+               return sb.toString();\r
+               \r
+       }\r
+       \r
+       @SuppressWarnings({ "rawtypes" })\r
+       public static String getBody(String parent, Object root, Class rootClass, ParameterizedType rootParam) throws ClassCastException {\r
+               \r
+               StringBuilder sb = new StringBuilder();\r
+               \r
+               // null値ならオブジェクトの種類とか気にしなくていいよね\r
+               if ( root == null ) {\r
+                       sb.append(parent);\r
+                       sb.append(SPMK_SEP);\r
+                       sb.append(SPCH_NULL);\r
+                       sb.append(SPMK_LF);\r
+                       return sb.toString();\r
+               }\r
+               \r
+               // 自身がArrayListのサブクラスだった場合に子要素をひとつずつテキスト化する\r
+               if ( root instanceof ArrayList ) {\r
+                       \r
+                       if ( ((ArrayList) root).size() == 0 ) {\r
+                               // 空の配列\r
+                               sb.append(SPHD_NOE);\r
+                               sb.append(parent);\r
+                               sb.append(SPMK_LF);\r
+                               return sb.toString();\r
+                       }\r
+                       \r
+                       // デシリアライズ可能かどうか、パラメータの型を確認する\r
+                       ParameterizedType paramType = ( rootParam != null ) ? rootParam : (ParameterizedType) root.getClass().getGenericSuperclass();\r
+                       if ( ! (paramType.getActualTypeArguments()[0] instanceof Class) ) {\r
+                               // 確認できなかったので、多分load()できない\r
+                               sb.append(SPHD_UNSOL);\r
+                               sb.append(parent);\r
+                               sb.append(SPMK_LF);\r
+                       }\r
+                       \r
+                       for ( Object obj : (ArrayList) root ) {\r
+                               String s;\r
+                               if ( obj != null ) {\r
+                                       s = getBody(parent+SPMK_ALELM,obj,obj.getClass(),null);\r
+                               }\r
+                               else {\r
+                                       s = getBody(parent+SPMK_ALELM,null,null,null);\r
+                               }\r
+                               if ( s == null ) {\r
+                                       return null;\r
+                               }\r
+                               \r
+                               sb.append(s);\r
+                       }\r
+\r
+                       if ( root.getClass() == ArrayList.class ) {\r
+                               return sb.toString();\r
+                       }\r
+                       \r
+                       // フィールドのシリアライズに続く\r
+               }\r
+               // 自身がHashMapのサブクラスだった場合に子要素をひとつずつテキスト化する\r
+               else if ( root instanceof HashMap ) {\r
+                       \r
+                       if ( ((HashMap) root).size() == 0 ) {\r
+                               // 空の連想配列\r
+                               sb.append(SPHD_NOE);\r
+                               sb.append(parent);\r
+                               sb.append(SPMK_LF);\r
+                               return sb.toString();\r
+                       }\r
+                       \r
+                       // デシリアライズ可能かどうか、パラメータの型を確認する\r
+                       ParameterizedType paramType = ( rootParam != null ) ? rootParam : (ParameterizedType) root.getClass().getGenericSuperclass();\r
+                       if ( ! (paramType.getActualTypeArguments()[0] instanceof Class &&\r
+                                       paramType.getActualTypeArguments()[1] instanceof Class) ) {\r
+                               // 確認できなかったので、多分load()できない\r
+                               sb.append(SPHD_UNSOL);\r
+                               sb.append(parent);\r
+                               sb.append(SPMK_LF);\r
+                       }\r
+                       \r
+                       for ( Iterator it = ((HashMap) root).entrySet().iterator(); it.hasNext(); ) {\r
+                               Entry obj = (Entry) it.next();\r
+                               \r
+                               String ks;\r
+                               String vs;\r
+                               if ( obj.getKey() != null ) {\r
+                                       ks = getBody(parent+SPMK_HMELM_K,obj.getKey(),obj.getKey().getClass(),null);\r
+                               }\r
+                               else {\r
+                                       ks = getBody(parent+SPMK_HMELM_K,null,null,null);\r
+                               }\r
+                               if ( obj.getValue() != null ) {\r
+                                       vs = getBody(parent+SPMK_HMELM_V,obj.getValue(),obj.getValue().getClass(),null);\r
+                               }\r
+                               else {\r
+                                       vs = getBody(parent+SPMK_HMELM_V,null,null,null);\r
+                               }\r
+                               \r
+                               if ( ks == null || vs == null ) {\r
+                                       return null;\r
+                               }\r
+                               \r
+                               sb.append(ks);\r
+                               sb.append(vs);\r
+                       }\r
+                       \r
+                       if ( root.getClass() == HashMap.class || root.getClass().getSuperclass() == HashMap.class ) {\r
+                               return sb.toString();\r
+                       }\r
+                       \r
+                       // フィールドのシリアライズに続く\r
+               }\r
+               // 特別な型はそのままでいーんじゃない?(自身)\r
+               else {\r
+                       String vs = obj2str(root,rootClass);\r
+                       if ( vs != null ) {\r
+                               sb.append(parent);\r
+                               sb.append(SPMK_SEP);\r
+                               sb.append(vs);\r
+                               sb.append(SPMK_LF);\r
+                               \r
+                               return sb.toString();   // おわれ\r
+                       }\r
+               }\r
+\r
+               Field[] fd = rootClass.getDeclaredFields();\r
+               for ( Field fx : fd ) {\r
+                       fx.setAccessible(true);\r
+                       \r
+                       // finalは駄目\r
+                       if ( Modifier.isFinal(fx.getModifiers()) ) {\r
+                               continue;\r
+                       }\r
+                       // staticは駄目\r
+                       if ( Modifier.isStatic(fx.getModifiers()) ) {\r
+                               continue;\r
+                       }\r
+\r
+                       try {\r
+                               \r
+                               // フィールドの解析\r
+                               String key = fx.getName();\r
+                               Class cls = fx.getType();\r
+                               Object obj = fx.get(root);\r
+\r
+                               // フィールド変数のジェネリクスを解決するための情報を取得する\r
+                               Type ty = fx.getGenericType();\r
+                               ParameterizedType pty = (ParameterizedType) ((ty instanceof ParameterizedType) ? ty : null);\r
+\r
+                               // 使用禁止は駄目\r
+                               if ( fx.getAnnotation(Deprecated.class) != null ) {\r
+                                       sb.append(SPHD_DEP);\r
+                                       sb.append(parent);\r
+                                       sb.append(SPMK_DOT);\r
+                                       sb.append(key);\r
+                                       sb.append(CMNT_AS);\r
+                                       sb.append(cls.getName());\r
+                                       sb.append(SPMK_LF);\r
+                                       continue;\r
+                               }\r
+                               \r
+                               // 特別な型はそのままでいーんじゃない?(フィールド)\r
+                               {\r
+                                       String vs = obj2str(obj,cls);\r
+                                       if ( vs != null ) {\r
+                                               sb.append(parent);\r
+                                               sb.append(SPMK_DOT);\r
+                                               sb.append(key);\r
+                                               sb.append(SPMK_SEP);\r
+                                               sb.append(vs);\r
+                                               sb.append(SPMK_LF);\r
+                                               continue;\r
+                                       }\r
+                               }\r
+                               \r
+                               // 掘り下げる\r
+                               sb.append(getBody(parent+SPMK_DOT+key,obj,cls,pty));\r
+                       }\r
+                       catch (Exception e) {\r
+                               e.printStackTrace();\r
+                               return null;\r
+                       }\r
+               }\r
+\r
+               return sb.toString();\r
+       }\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * デシリアライズ\r
+        ******************************************************************************/\r
+       \r
+       @SuppressWarnings({ "rawtypes", "unchecked" })\r
+       public static boolean load(String envText, Object root) {\r
+               \r
+       if ( ! new File(envText).exists() ) {\r
+               return false;\r
+       }\r
+       \r
+       System.out.println(MSGID+"テキスト形式で読み込みます: "+envText);\r
+       String buf = CommonUtils.read4file(envText, false);\r
+       if ( buf == null ) {\r
+               return false;\r
+       }\r
+       \r
+       // ArrayListのサブクラスならばパラメータ型を控えておく \r
+       Class alparam = null;\r
+       Field[] alfd = null;\r
+       Class hmparam_k = null;\r
+       Class hmparam_v = null;\r
+       Field[] hmfd_k = null;\r
+       Field[] hmfd_v = null;\r
+       try {\r
+               if ( root instanceof ArrayList ) {\r
+                               ParameterizedType paramType = (ParameterizedType) root.getClass().getGenericSuperclass();\r
+                               alparam = (Class) paramType.getActualTypeArguments()[0];\r
+                               alfd = alparam.getDeclaredFields();\r
+               }\r
+               else if ( root instanceof HashMap ) {\r
+                               ParameterizedType paramType = (ParameterizedType) root.getClass().getGenericSuperclass();\r
+                               hmparam_k = (Class) paramType.getActualTypeArguments()[0];\r
+                               hmparam_v = (Class) paramType.getActualTypeArguments()[1];\r
+                               hmfd_k = hmparam_k.getDeclaredFields();\r
+                               hmfd_v = hmparam_v.getDeclaredFields();\r
+               }\r
+       }\r
+       catch ( ClassCastException e ) {\r
+               e.printStackTrace();\r
+               return false;\r
+       }\r
+       \r
+       // フィールド\r
+       Field[] tmpFd = root.getClass().getDeclaredFields();\r
+       \r
+       Object tmpRoot = root;\r
+       Object keyRoot = null;\r
+       String[] lines = buf.split(SPMK_LF);\r
+       for ( int lineno=1; lines.length>=lineno; lineno++ ) {\r
+               \r
+               String str = lines[lineno-1];\r
+               \r
+               if ( str.startsWith(SPHD_MOD) ) {\r
+                       System.out.println(MSGID+str);\r
+                       continue;\r
+               }\r
+               \r
+               if ( str.startsWith(SPMK_CM) || str.matches("^\\s*$") ) {\r
+                       continue;\r
+               }\r
+               \r
+               if ( str.startsWith(SPMK_ALELM) ) {\r
+                       if ( alparam == null ) {\r
+                               return true;    // 終了していいよ\r
+                       }\r
+                       \r
+                       // 自身がArrayListのサブクラスだった場合に子要素をひとつずつオブジェクト化する\r
+                       try {\r
+                               if ( str.startsWith(SPMK_ALELM+SPMK_SEP) ) {\r
+                                       // 特殊型の場合\r
+                                       tmpRoot = str2obj(str.substring((SPMK_ALELM+SPMK_SEP).length()),alparam);\r
+                                       \r
+                                       ((ArrayList) root).add(tmpRoot);\r
+                               }\r
+                               else {\r
+                                       // 通常型の場合\r
+                                       tmpRoot = alparam.newInstance();\r
+                                       tmpFd = alfd;\r
+                                       \r
+                                       ((ArrayList) root).add(tmpRoot);\r
+                               }\r
+                               continue;\r
+                       }\r
+                       catch ( Exception e ) {\r
+                               System.err.println(ERRID+"オブジェクトのインスタンスが作成できません.");\r
+                               e.printStackTrace();\r
+                               return false;\r
+                       }\r
+               }\r
+               else if ( str.startsWith(SPMK_HMELM_K) ) {\r
+                       if ( hmparam_k == null ) {\r
+                               return true;    // 終了していいよ\r
+                       }\r
+                       \r
+                       // 自身がHashMapのサブクラスだった場合にキー要素をオブジェクト化する\r
+                       try {\r
+                               if ( str.startsWith(SPMK_HMELM_K+SPMK_SEP) ) {\r
+                                       // 特殊型の場合\r
+                                       keyRoot = str2obj(str.substring((SPMK_HMELM_K+SPMK_SEP).length()),hmparam_k);\r
+                                       tmpRoot = null;\r
+                                       tmpFd = null;\r
+                               }\r
+                               else {\r
+                                       // 通常型の場合\r
+                                       keyRoot = tmpRoot = hmparam_k.newInstance();\r
+                                       tmpFd = hmfd_k;\r
+                               }\r
+                               continue;\r
+                       }\r
+                       catch ( Exception e ) {\r
+                               System.err.println(ERRID+"オブジェクトのインスタンスが作成できません.");\r
+                               e.printStackTrace();\r
+                               return false;\r
+                       }\r
+               }\r
+               else if ( str.startsWith(SPMK_HMELM_V) ) {\r
+                       if ( hmparam_v == null ) {\r
+                               return true;    // 終了していいよ\r
+                       }\r
+                       \r
+                       // 自身がHashMapのサブクラスだった場合にバリュー要素をオブジェクト化する\r
+                       try {\r
+                               if ( str.startsWith(SPMK_HMELM_V+SPMK_SEP) ) {\r
+                                       // 特殊型の場合\r
+                                       tmpRoot = str2obj(str.substring((SPMK_HMELM_V+SPMK_SEP).length()),hmparam_v);\r
+                                       \r
+                                       ((HashMap) root).put(keyRoot, tmpRoot);\r
+                                       keyRoot = tmpRoot = null;\r
+                                       tmpFd = null;\r
+                               }\r
+                               else {\r
+                                       // 通常型の場合\r
+                                       tmpRoot = hmparam_v.newInstance();\r
+                                       tmpFd = hmfd_v;\r
+                                       \r
+                                       ((HashMap) root).put(keyRoot,tmpRoot);\r
+                                       keyRoot = null;\r
+                               }\r
+                               continue;\r
+                       }\r
+                       catch ( Exception e ) {\r
+                               System.err.println(ERRID+"オブジェクトのインスタンスが作成できません.");\r
+                               e.printStackTrace();\r
+                               return false;\r
+                       }\r
+               }\r
+               \r
+               String[] a = str.split(SPMK_SEP, 2);\r
+               if ( a.length != 2 ) {\r
+                       System.err.println(ERRID+"不正な記述: "+envText+" at "+lineno+"行目 "+str);\r
+                       return false;\r
+               }\r
+               \r
+               if ( ! setBody(tmpRoot,tmpFd,a,envText,lineno,str) ) {\r
+                       return false;\r
+               }\r
+               \r
+       }\r
+       \r
+               return true;\r
+               \r
+       }\r
+       \r
+       @SuppressWarnings({ "rawtypes", "unchecked" })\r
+       private static boolean setBody(Object root, Field[] fd, String[] a, String envText, int lineno, String str) {\r
+               \r
+               Field fx = null;\r
+               for ( Field f : fd ) {\r
+                       if ( f.getName().equals(a[0].replaceFirst("\\[\\d+\\]$","")) ) {\r
+                               fx = f;\r
+                               break;\r
+                       }\r
+               }\r
+               if ( fx == null ) {\r
+                       System.err.println(ERRID+"不正な記述: "+envText+" at "+lineno+"行目 "+str);\r
+                       return false;   // エラー\r
+               }\r
+               \r
+               fx.setAccessible(true);\r
+               \r
+               // static、finalで修飾された変数\r
+               if ( Modifier.isFinal(fx.getModifiers()) ) {\r
+                       return true;    // スキップ\r
+               }\r
+               if ( Modifier.isStatic(fx.getModifiers()) ) {\r
+                       return true;    // スキップ\r
+               }\r
+               \r
+               // ディスコンな変数\r
+               if ( fx.getAnnotation(Deprecated.class) != null ) {\r
+                       System.out.println(MSGID+SPHD_DEP+fx.getName());\r
+                       return true;    // スキップ\r
+               }\r
+               \r
+               Class cls = fx.getType();\r
+               \r
+               try {\r
+                       if ( cls == ArrayList.class ) {\r
+                               ArrayList list = (ArrayList) fx.get(root);\r
+                               if ( fx.get(root) == null ) {\r
+                                       System.out.println(ERRID+"初期化されていないフィールド: "+envText+" at "+lineno+"行目 ("+cls.getName()+") "+str);\r
+                                       return false;   // エラー\r
+                               }\r
+                               \r
+                               if ( a[0].endsWith("[0]") ) {\r
+                                       // no element.\r
+                                       list.clear();\r
+                               }\r
+                               else {\r
+                                       if ( a[0].endsWith("[1]") ) {\r
+                                               // newした時のデフォルト値が入っているからリセットじゃー\r
+                                               list.clear();\r
+                                       }\r
+                                       ParameterizedType paramType = (ParameterizedType) fx.getGenericType();\r
+                                       Class ocls = (Class) paramType.getActualTypeArguments()[0];\r
+                                       Object obj = str2obj(a[1],ocls);\r
+                                       list.add(obj);\r
+                               }\r
+                       }\r
+                       else if ( cls == HashMap.class ) {\r
+                               HashMap map = (HashMap) fx.get(root);\r
+                               if ( fx.get(root) == null ) {\r
+                                       System.out.println(ERRID+"初期化されていないフィールド: "+envText+" at "+lineno+"行目 ("+cls.getName()+") "+str);\r
+                                       return false;   // エラー\r
+                               }\r
+                               String[] b = a[1].split(Pattern.quote(SPCH_LF),2);\r
+                               if ( b.length != 2 ) {\r
+                               System.err.println(ERRID+"不正な記述: "+envText+" at "+lineno+"行目 "+str);\r
+                                       return false;   // エラー\r
+                               }\r
+                               \r
+                               if ( a[0].endsWith("[0]") ) {\r
+                                       // no element.\r
+                                       map.clear();\r
+                               }\r
+                               else {\r
+                                       if ( a[0].endsWith("[1]") ) {\r
+                                               // newした時のデフォルト値が入っているからリセットじゃー\r
+                                               map.clear();\r
+                                       }\r
+                                       ParameterizedType paramType = (ParameterizedType) fx.getGenericType();\r
+                                       Class kcls = (Class) paramType.getActualTypeArguments()[0];\r
+                                       Class vcls = (Class) paramType.getActualTypeArguments()[1];\r
+                                       Object k = str2obj(b[0],kcls);\r
+                                       Object v = str2obj(b[1],vcls);\r
+                                       map.put(k,v);\r
+                               }\r
+                       }\r
+                       else {\r
+                               Object obj = str2obj(a[1],cls);\r
+                               fx.set(root, obj);\r
+                       }\r
+                       \r
+                       return true;    // 成功\r
+               }\r
+               catch (UnsupportedOperationException e) {\r
+                       System.out.println(ERRID+e.getMessage()+": "+envText+" at "+lineno+"行目 ("+cls.getName()+") "+str);\r
+               }\r
+               catch (NoSuchObjectException e) {\r
+                       System.out.println(ERRID+e.getMessage()+": "+envText+" at "+lineno+"行目 ("+cls.getName()+") "+str);\r
+               }\r
+               catch (ClassCastException e) {\r
+                       System.out.println(ERRID+e.getMessage()+": "+envText+" at "+lineno+"行目 ("+cls.getName()+") "+str);\r
+               }\r
+               catch (Exception e) {\r
+                       // エラー項目はスキップする\r
+                       System.out.println(ERRID+e.getMessage()+": "+envText+" at "+lineno+"行目 ("+cls.getName()+") "+str);\r
+                       e.printStackTrace();\r
+               }\r
+               \r
+               return false;   //エラー\r
+       }\r
+       \r
+       /*******************************************************************************\r
+        * シリアライズ(部品)\r
+        ******************************************************************************/\r
+       \r
+       @SuppressWarnings("rawtypes")\r
+       private static String obj2str(Object obj, Class cls) {\r
+               // 基本的なオブジェクト\r
+               if ( cls == String.class ) {\r
+                       return(obj == null ? SPCH_NULL : ((String) obj).replaceAll(SPMK_LF, SPCH_LF));\r
+               }\r
+               else if ( cls == boolean.class || cls == Boolean.class ) {\r
+                       return(obj == null ? SPCH_NULL : String.valueOf((Boolean) obj));\r
+               }\r
+               else if ( cls == int.class || cls == Integer.class ) {\r
+                       return(obj == null ? SPCH_NULL : String.valueOf((Integer) obj));\r
+               }\r
+               else if ( cls == float.class || cls == Float.class ) {\r
+                       return(obj == null ? SPCH_NULL : String.valueOf((Float) obj));\r
+               }\r
+               else if ( cls == double.class || cls == Double.class ) {\r
+                       return(obj == null ? SPCH_NULL : String.valueOf((Float) obj));\r
+               }\r
+               // 特別扱いしたいオブジェクト\r
+               else if ( cls == Color.class ) {\r
+                       return(obj == null ? SPCH_NULL : CommonUtils.color2str((Color) obj));\r
+               }\r
+               else if ( cls.isEnum() ) {\r
+                       return(obj == null ? SPCH_NULL : obj.toString());\r
+               }\r
+               /*\r
+               else if ( cls == Rectangle.class ) {\r
+                       Rectangle ra = (Rectangle) obj;\r
+                       return(obj == null ? SPCH_NULL : String.format("%d,%d,%d,%d",ra.x,ra.y,ra.width,ra.height));\r
+               }\r
+               else if ( cls == DblClkCmd.class ) {\r
+                       return(obj == null ? SPCH_NULL : String.valueOf(((DblClkCmd) obj).getId()));\r
+               }\r
+               else if ( cls == SnapshotFmt.class ) {\r
+                       return(obj == null ? SPCH_NULL : String.valueOf(((SnapshotFmt) obj).getId()));\r
+               }\r
+               else if ( cls == AAMode.class ) {\r
+                       return(obj == null ? SPCH_NULL : String.valueOf(((AAMode) obj).getId()));\r
+               }\r
+               else if ( cls == UpdateOn.class ) {\r
+                       return(obj == null ? SPCH_NULL : String.valueOf(((UpdateOn) obj).getId()));\r
+               }\r
+               else if ( cls == FontStyle.class ) {\r
+                       return(obj == null ? SPCH_NULL : String.valueOf(((FontStyle) obj).getId()));\r
+               }\r
+               else if ( cls == TextValueSet.class ) {\r
+                       TextValueSet t = (TextValueSet) obj;\r
+                       return(obj == null ? SPCH_NULL : t.getText()+SPCH_LF+t.getValue());\r
+               }\r
+               else if ( cls == ProgOption.class ) {\r
+                       return(obj == null ? SPCH_NULL : ((ProgOption) obj).toString());\r
+               }\r
+               /*\r
+               else if ( obj instanceof Entry ) {\r
+                       Entry t = (Entry) obj;\r
+                       String k = obj2str(t.getKey(), t.getKey().getClass());\r
+                       String v = obj2str(t.getValue(), t.getValue().getClass());\r
+                       return(obj == null ? SPCH_NULL : k+SPCH_LF+v);\r
+               }\r
+               */\r
+               \r
+               return null;\r
+       }\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * デシリアライズ(部品)\r
+        * @throws NoSuchObjectException \r
+        ******************************************************************************/\r
+       \r
+       @SuppressWarnings("rawtypes")\r
+       private static Object str2obj(String str, Class cls) throws UnsupportedOperationException, NoSuchObjectException {\r
+               if ( cls == String.class ) {\r
+                       return(str.equals(SPCH_NULL) ? null : str.replaceAll(SPCH_LF, SPMK_LF));\r
+               }\r
+               else if ( cls == int.class || cls == Integer.class ) {\r
+                       try {\r
+                               return(str.equals(SPCH_NULL) ? null : Integer.valueOf(str));\r
+                       }\r
+                       catch ( NumberFormatException e ) {\r
+                               throw new UnsupportedOperationException("数値に変換できない");\r
+                       }\r
+               }\r
+               else if ( cls == float.class || cls == Float.class ) {\r
+                       try {\r
+                               return(str.equals(SPCH_NULL) ? null : Float.valueOf(str));\r
+                       }\r
+                       catch ( NumberFormatException e ) {\r
+                               throw new UnsupportedOperationException("数値に変換できない");\r
+                       }\r
+               }\r
+               else if ( cls == boolean.class || cls == Boolean.class ) {\r
+                       return(str.equals(SPCH_NULL) ? null : Boolean.valueOf(str));\r
+               }\r
+               else if ( cls == Rectangle.class ) {\r
+                       try {\r
+                               String[] a = str.split(",");\r
+                               if ( a.length == 4 ) {\r
+                                       return(str.equals(SPCH_NULL) ? null : new Rectangle(Integer.valueOf(a[0]),Integer.valueOf(a[1]),Integer.valueOf(a[2]),Integer.valueOf(a[3])));\r
+                               }\r
+                               else {\r
+                                       throw new UnsupportedOperationException("変換できない");\r
+                               }\r
+                       }\r
+                       catch ( NumberFormatException e ) {\r
+                               throw new UnsupportedOperationException("数値に変換できない");\r
+                       }\r
+               }\r
+               else if ( cls == Color.class ) {\r
+                       Color c = CommonUtils.str2color(str);\r
+                       if ( c != null ) {\r
+                               return(c);\r
+                       }\r
+                       else {\r
+                               throw new UnsupportedOperationException("色に変換できない ");\r
+                       }\r
+               }\r
+               else if ( cls == DblClkCmd.class ) {\r
+                       DblClkCmd dcc = DblClkCmd.get(str);\r
+                       if ( dcc != null ) {\r
+                               return(dcc);\r
+                       }\r
+                       else {\r
+                               throw new UnsupportedOperationException("変換できない");\r
+                       }\r
+               }\r
+               else if ( cls == SnapshotFmt.class ) {\r
+                       SnapshotFmt sf = SnapshotFmt.get(str);\r
+                       if ( sf != null ) {\r
+                               return(sf);\r
+                       }\r
+                       else {\r
+                               throw new UnsupportedOperationException("変換できない");\r
+                       }\r
+               }\r
+               else if ( cls == AAMode.class ) {\r
+                       AAMode aam = AAMode.get(str);\r
+                       if ( aam != null ) {\r
+                               return(aam);\r
+                       }\r
+                       else {\r
+                               throw new UnsupportedOperationException("変換できない");\r
+                       }\r
+               }\r
+               else if ( cls == UpdateOn.class ) {\r
+                       UpdateOn uo = UpdateOn.get(str);\r
+                       if ( uo != null ) {\r
+                               return(uo);\r
+                       }\r
+                       else {\r
+                               throw new UnsupportedOperationException(ERRID+"変換できない");\r
+                       }\r
+               }\r
+               else if ( cls == FontStyle.class ) {\r
+                       FontStyle fs = FontStyle.get(str);\r
+                       if ( fs != null ) {\r
+                               return(fs);\r
+                       }\r
+                       else {\r
+                               throw new UnsupportedOperationException("変換できない");\r
+                       }\r
+               }\r
+               else if ( cls == TextValueSet.class ) {\r
+                       String a[] = str.split(Pattern.quote(SPCH_LF),2);\r
+                       if ( a.length == 2 ) {\r
+                               TextValueSet t = new TextValueSet();\r
+                               t.setText(a[0]);\r
+                               t.setValue(a[1]);\r
+                               return (t);\r
+                       }\r
+                       else {\r
+                               throw new UnsupportedOperationException("変換できない");\r
+                       }\r
+               }\r
+               else if ( cls == ProgOption.class ) {\r
+                       for ( ProgOption po : ProgOption.values() ) {\r
+                               if ( po.toString().equals(str) ) {\r
+                                       return po;\r
+                               }\r
+                       }\r
+                       throw new UnsupportedOperationException("変換できない");\r
+               }\r
+               \r
+               throw new NoSuchObjectException("未対応の項目");\r
+       }\r
+       \r
+}\r
index 076d3c0..0d967a9 100644 (file)
@@ -8,7 +8,9 @@ import java.util.ArrayList;
  */\r
 public interface HDDRecorder {\r
 \r
-       // 定数\r
+       /*******************************************************************************\r
+        * 定数\r
+        ******************************************************************************/\r
        \r
        /**\r
         * 繰り返し予約を表す文字列定数。(毎日曜日~毎日)\r
@@ -33,7 +35,15 @@ public interface HDDRecorder {
         */\r
        public static final int SCOPEMAX = 366;\r
 \r
-       // 種族の特性\r
+       // 特殊なレコーダID\r
+       public static final String SELECTED_ALL = "すべて";\r
+       public static final String SELECTED_PICKUP = "ピックアップのみ";\r
+\r
+       \r
+       /*******************************************************************************\r
+        * 種族の特性\r
+        ******************************************************************************/\r
+\r
        public String getRecorderId();\r
        \r
        public RecType getType();\r
diff --git a/TinyBannavi/src/tainavi/HDDRecorderChangeEvent.java b/TinyBannavi/src/tainavi/HDDRecorderChangeEvent.java
new file mode 100644 (file)
index 0000000..c798f06
--- /dev/null
@@ -0,0 +1,17 @@
+package tainavi;\r
+\r
+import javax.swing.event.ChangeEvent;\r
+\r
+\r
+/**\r
+ * ツールバーのレコーダ選択コンボボックスが操作されたよイベントオブジェクト\r
+ */\r
+public class HDDRecorderChangeEvent extends ChangeEvent {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       public HDDRecorderChangeEvent(HDDRecorderSelectable source) {\r
+               super(source);\r
+       }\r
+\r
+}\r
index 928d991..a0701e5 100644 (file)
@@ -4,6 +4,7 @@ import java.util.ArrayList;
 \r
 import tainavi.HDDRecorder.RecType;\r
 \r
+\r
 /**\r
  * {@link HDDRecorder} のリストを実現するクラスです. \r
  * @version 3.15.4β~\r
@@ -11,8 +12,9 @@ import tainavi.HDDRecorder.RecType;
 public class HDDRecorderList extends ArrayList<HDDRecorder> {\r
 \r
        private static final long serialVersionUID = 1L;\r
-\r
-       private static final HDDRecorderList mylist = new HDDRecorderList();\r
+       \r
+       // ↓ 自己フィールド生成を行うor自己フィールド生成によるスタックオーバーフローを回避する(static修飾)ための異常なコード(自戒のためにコメントとして残す)\r
+       //private static final HDDRecorderList mylist = new HDDRecorderList();\r
        \r
        // レコーダIDから種類を調べる\r
        public RecType getRecId2Type(String recId) {\r
@@ -24,33 +26,39 @@ public class HDDRecorderList extends ArrayList<HDDRecorder> {
        }\r
        \r
        /**\r
-        *  レコーダIDに合ったプラグイン(種族)を探す\r
+        *  レコーダIDに合ったプラグイン(一族郎党)を探す\r
         */\r
        public HDDRecorderList findPlugin(String recId) {\r
                if ( recId == null ) {\r
                        return this;\r
                }\r
-               HDDRecorderList list = new HDDRecorderList();\r
+               \r
+               HDDRecorderList mylist = new HDDRecorderList();\r
                for ( HDDRecorder rec : this ) {\r
                        if ( recId.equals(rec.getRecorderId()) ) {\r
-                               list.add(rec);\r
+                               mylist.add(rec);\r
                        }\r
                }\r
-               return list;\r
+               return mylist;\r
        }\r
        \r
        /**\r
         * 実レコーダのプラグイン(個体)を探す\r
-        * @return 本来{@link HDDRecorder}を返すべきだが、呼び出し側の処理を書きやすくするために{@link HDDRecorderList}を返す。よって、==nullではなく.size()==0で確認する。\r
-        * @param myself 「すべて」を指定する場合はNULLをどうぞ\r
+        * @param mySelf 「すべて」を指定する場合はNULLをどうぞ\r
+        * @return\r
+        * <P> 「すべて」「ピックアップのみ」→全部のインスタンスを返す \r
+        * <P> 「個別指定」→本来{@link HDDRecorder}を返すべきだが、呼び出し側の処理を書きやすくするために{@link HDDRecorderList}を返す。よって、==nullではなく.size()==0で確認する。\r
         */\r
-       public HDDRecorderList findInstance(String myself) {\r
-               if (myself == null || myself.length() == 0) {\r
+       public HDDRecorderList findInstance(String mySelf) {\r
+               if (mySelf == null || mySelf.length() == 0) {\r
+                       // 「すべて」「ピックアップのみ」→全部のインスタンスを返す\r
                        return this;\r
                }\r
-               mylist.clear();\r
+               \r
+               // 個別指定\r
+               HDDRecorderList mylist = new HDDRecorderList();\r
                for ( HDDRecorder rec : this ) {\r
-                       if ( rec.isMyself(myself) ) {\r
+                       if ( rec.isMyself(mySelf) ) {\r
                                mylist.add(rec);\r
                                break;\r
                        }\r
diff --git a/TinyBannavi/src/tainavi/HDDRecorderListener.java b/TinyBannavi/src/tainavi/HDDRecorderListener.java
new file mode 100644 (file)
index 0000000..51fbe35
--- /dev/null
@@ -0,0 +1,27 @@
+package tainavi;\r
+\r
+import java.util.EventListener;\r
+\r
+\r
+/**\r
+ * レコーダの状態変化を各コンポーネントに伝達するリスナー\r
+ * @see HDDRecorderSelectionEvent\r
+ */\r
+public interface HDDRecorderListener extends EventListener {\r
+       \r
+       // 定数\r
+       public static final String SELECTED_ALL = null;\r
+       public static final String SELECTED_PICKUP = "";\r
+       \r
+       /**\r
+        * レコーダーの選択イベント\r
+        */\r
+       public void valueChanged(HDDRecorderSelectionEvent e);\r
+\r
+       /**\r
+        * レコーダーの情報変更イベント\r
+        */\r
+       public void stateChanged(HDDRecorderChangeEvent e);\r
+\r
+       \r
+}\r
diff --git a/TinyBannavi/src/tainavi/HDDRecorderSelectable.java b/TinyBannavi/src/tainavi/HDDRecorderSelectable.java
new file mode 100644 (file)
index 0000000..6e1ca86
--- /dev/null
@@ -0,0 +1,27 @@
+package tainavi;\r
+\r
+public interface HDDRecorderSelectable {\r
+       \r
+       /**\r
+        * レコーダ選択イベントリスナー\r
+        */\r
+       \r
+       public void addHDDRecorderSelectionListener(HDDRecorderListener l);\r
+\r
+       public void removeHDDRecorderSelectionListener(HDDRecorderListener l);\r
+\r
+       public String getSelectedId();\r
+       \r
+       public HDDRecorderList getSelectedList();\r
+\r
+       \r
+       /**\r
+        * レコーダ情報変更イベントリスナー\r
+        */\r
+       \r
+       public void addHDDRecorderChangeListener(HDDRecorderListener l);\r
+\r
+       public void removeHDDRecorderChangeListener(HDDRecorderListener l);\r
+       \r
+\r
+}\r
diff --git a/TinyBannavi/src/tainavi/HDDRecorderSelectionEvent.java b/TinyBannavi/src/tainavi/HDDRecorderSelectionEvent.java
new file mode 100644 (file)
index 0000000..ab1b5fb
--- /dev/null
@@ -0,0 +1,18 @@
+package tainavi;\r
+\r
+import java.util.EventObject;\r
+\r
+\r
+/**\r
+ * ツールバーのレコーダ選択コンボボックスが操作されたよイベントオブジェクト\r
+ */\r
+public class HDDRecorderSelectionEvent extends EventObject {\r
+       \r
+       private static final long serialVersionUID = 1L;\r
+       \r
+       // この引数の群れはいいのか?\r
+       public HDDRecorderSelectionEvent(Object source) {\r
+               super(source);\r
+       }\r
+\r
+}\r
index 1d5eb11..fbb29b5 100644 (file)
@@ -38,7 +38,7 @@ public class HDDRecorderUtils implements HDDRecorder,Cloneable {
        public HDDRecorderUtils clone() {\r
                try {\r
                        HDDRecorderUtils ru = (HDDRecorderUtils) super.clone();\r
-                       CommonUtils.FieldCopy(ru, this); // ディープコピーするよ\r
+                       FieldUtils.deepCopy(ru, this); // ディープコピーするよ\r
                        return ru;\r
                } catch (CloneNotSupportedException e) {\r
                        throw new InternalError(e.toString());\r
@@ -283,7 +283,7 @@ public class HDDRecorderUtils implements HDDRecorder,Cloneable {
         * 自動予約一覧\r
         */\r
        public AutoReserveInfoList getAutoReserves() { return AUTORESERVES; }\r
-       private AutoReserveInfoList AUTORESERVES = new AutoReserveInfoList(Env.envDir,"dummy","0.0.0.0","0");\r
+       private AutoReserveInfoList AUTORESERVES = new AutoReserveInfoList(Env.envDir,null,"dummy","0.0.0.0","0");\r
        \r
        /**\r
         * 録画済み一覧\r
index d43e104..0dfff2e 100644 (file)
@@ -72,7 +72,7 @@ public class PaperColorsMap extends HashMap<ProgGenre,Color> implements Cloneabl
                        PaperColorsMap cl = (PaperColorsMap) CommonUtils.readXML(cFile);\r
                        if ( cl != null ) {\r
                                System.out.println("ジャンル別背景色設定を読み込みました.");\r
-                               CommonUtils.FieldCopy(this, cl);\r
+                               FieldUtils.deepCopy(this, cl);\r
                                return true;\r
                        }\r
                }\r
index 8700f95..853b3e0 100644 (file)
@@ -549,7 +549,7 @@ public class PlugIn_RecDIGA_DMR_BWT2100 extends HDDRecorderUtils implements HDDR
                \r
                if ( rec_type_epg ) {\r
                        ReserveList newr = new ReserveList();\r
-                       CommonUtils.FieldCopy(newr, reqr);\r
+                       FieldUtils.deepCopy(newr, reqr);\r
                        if ( getDigaReserveDetail(newr, reqr.getId()) == null ) {\r
                                // 情報を取得できなかったので、鯛ナビの情報をそのままで\r
                                errmsg = "登録した予約の情報を取得しなおそうとしましたが、失敗しました。";\r
index 6548bda..e0e334d 100644 (file)
@@ -11,6 +11,8 @@ import java.util.HashMap;
 import java.util.regex.Matcher;\r
 import java.util.regex.Pattern;\r
 \r
+import taiSync.ReserveInfo;\r
+\r
 \r
 /**\r
  * \r
@@ -303,6 +305,8 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                \r
                System.out.println("レコーダの各種設定情報を取得します.");\r
                \r
+               errmsg = "";\r
+               \r
                /*\r
                 *  CHコード設定\r
                 */\r
@@ -422,8 +426,8 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
         *      レコーダーから予約一覧を取得する \r
         */\r
        @Override\r
-       public boolean GetRdReserve(boolean force)\r
-       {\r
+       public boolean GetRdReserve(boolean force) {\r
+       \r
                System.out.println("レコーダから予約一覧を取得します("+force+")");\r
                \r
                errmsg = "";\r
@@ -446,7 +450,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                \r
                // レコーダから読み出し(予約一覧)\r
                ArrayList<ReserveList> newReserveList = new ArrayList<ReserveList>();\r
-               if ( ! GetRdReservedList(newReserveList) ) {\r
+               if ( ! getRsvListAPI(newReserveList) ) {\r
                        return(false);\r
                }\r
                \r
@@ -478,25 +482,46 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
         *      レコーダーから自動予約一覧を取得する \r
         */\r
        @Override\r
-       public boolean GetRdAutoReserve(boolean force)\r
-       {\r
+       public boolean GetRdAutoReserve(boolean force) {\r
+       \r
                System.out.println("レコーダから自動予約一覧を取得します("+force+")");\r
                \r
                errmsg = "";\r
                \r
-               if ( ! force ) {\r
-                       return true;    // 実装完了までの暫定\r
+               AutoReserveInfoList newList = new AutoReserveInfoList(Env.envDir,null,getRecorderId(),getIPAddr(),getPortNo());\r
+               \r
+               if ( ! force && newList.exists() ) {\r
+                       // 既存のファイルがあれば読み出す\r
+                       if ( newList.load() ) {\r
+                               setAutoReserves(newList);\r
+                               return true;\r
+                       }\r
+                       \r
+                       // ★★★ログだせよ!\r
+                       \r
+                       return false;   // 読めなかったよ\r
                }\r
                \r
                // おまじない\r
                Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
                \r
-               AutoReserveInfoList newAutoReserveList = new AutoReserveInfoList(Env.envDir,getRecorderId(),getIPAddr(),getPortNo());\r
-               if ( ! GetRdAutoReserveList(newAutoReserveList) ) {\r
-                       return false;\r
+               // リモートから取得\r
+               if ( ! getAutoReserveList(newList) ) {\r
+                       if ( newList.exists() ) {\r
+                               // 過去に取得したことがあるなら通信エラーとして処理\r
+                               return false;\r
+                       }\r
+                       else {\r
+                               // 過去に取得したことがあるないのでスキップ扱い(にしないと移行時に録画結果一覧が表示されないよね)\r
+                               return true;\r
+                       }\r
                }\r
                \r
-               setAutoReserves(newAutoReserveList);\r
+               setAutoReserves(newList);\r
+               \r
+               if ( ! newList.save() ) {\r
+                       // ★★★ログだせよ!\r
+               }\r
                \r
                return true;\r
        }\r
@@ -531,10 +556,10 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                        return true;\r
                }\r
                \r
-               if ( ! GetRdRecordedList(newRecordedList) ) {\r
+               if ( ! getRecedList(newRecordedList) ) {\r
                        return false;\r
                }\r
-               if ( ! GetRdRecordedListDetailAll(newRecordedList) ) {\r
+               if ( ! getRecedDetailAll(newRecordedList) ) {\r
                        return false;\r
                }\r
                setRecorded(newRecordedList);                           // 置き換え\r
@@ -548,7 +573,15 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                return true;\r
        }\r
        \r
-       private boolean GetRdReservedList(ArrayList<ReserveList> newReserveList) {\r
+       \r
+       /*------------------------------------------------------------------------------\r
+        * 予約一覧の取得\r
+        *------------------------------------------------------------------------------/\r
+       \r
+       /**\r
+        * 予約一覧+詳細の取得【API版】\r
+        */\r
+       private boolean getRsvListAPI(ArrayList<ReserveList> newReserveList) {\r
                \r
                // RDから予約一覧を取り出す\r
                String response="";\r
@@ -1002,30 +1035,47 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                return true;\r
        }\r
 \r
-       private boolean GetRdReservedDetailByContentId(ReserveList r, int cnt) {\r
+       /**\r
+        * 予約詳細の取得【HTML版】(番組IDキー)\r
+        */\r
+       private boolean getRsvDetailByContentId(ReserveList r, int cnt) {\r
                String pstr = genPoststrEPGA(r);\r
                String url = "http://"+getIPAddr()+":"+getPortNo()+"/epginfo.html?"+pstr;\r
                System.out.println("URL: "+url);\r
-               return _GetRdReservedDetail(r, url, cnt);\r
+               return getRsvDetail(r, url, cnt);\r
        }\r
-       private boolean GetRdReservedDetailByReserveId(ReserveList r, int cnt) {\r
+       \r
+       /**\r
+        * 予約詳細の取得【HTML版】(予約IDキー)\r
+        */\r
+       private boolean getRsvDetailByReserveId(ReserveList r, int cnt) {\r
                String url = "http://"+getIPAddr()+":"+getPortNo()+"/reserveinfo.html?id="+getRsvId(r.getId());\r
                System.out.println("URL: "+url);\r
-               return _GetRdReservedDetail(r, url, cnt);\r
+               return getRsvDetail(r, url, cnt);\r
        }\r
-       private boolean _GetRdReservedDetail(ReserveList r, String url, int cnt) {\r
+       \r
+       /**\r
+        * 予約詳細の取得【HTML版】(共通)\r
+        */\r
+       private boolean getRsvDetail(ReserveList r, String url, int cnt) {\r
                \r
                reportProgress("+予約詳細を取得します("+cnt+")");\r
 \r
                String[] d = reqGET(url,null);\r
-               //String hdr = d[0];\r
-               String res = d[1];\r
-               Matcher mb = null;\r
-               \r
-               if (res == null) {\r
+               if ( d[1] == null ) {\r
                        return false;\r
                }\r
                \r
+               return decodeRsvDetail(r, d[1], url);\r
+       }\r
+\r
+       /**\r
+        * 予約詳細のデコード【HTML版】\r
+        */\r
+       private boolean decodeRsvDetail(ReserveList r, String res, String url) {\r
+\r
+               Matcher mb = null;\r
+               \r
                try {\r
                        // 予約ID\r
                        mb = Pattern.compile("<form method=\"POST\" action=\"reservedel\\.html\\?id=(\\d+?)\">").matcher(res);\r
@@ -1109,7 +1159,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                // (1-3)録画モード\r
                {\r
                        String rec_mode = getSelectedSetting("recMode",res);\r
-                       if ( rec_mode.equals(ITEM_REC_MODE_DISABLE) ) {\r
+                       if ( rec_mode != null && rec_mode.equals(ITEM_REC_MODE_DISABLE) ) {\r
                                // "無効"は「予約実行」で扱うので\r
                                r.setExec(false);\r
                                setTextRecMode(r,getListRecMode().get(0).getText());\r
@@ -1202,7 +1252,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                ArrayList<String> pRecNamePlugIn = new ArrayList<String>();\r
                \r
                // 録画後実行bat\r
-               mb = Pattern.compile("録画後実行bat.*?:\\s*(.*?)<BR>",Pattern.DOTALL).matcher(d[1]);\r
+               mb = Pattern.compile("録画後実行bat.*?:\\s*(.*?)<BR>",Pattern.DOTALL).matcher(res);\r
                if ( mb.find() ) {\r
                        batFilePath = mb.group(1);\r
                }\r
@@ -1210,7 +1260,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                // オプショナル\r
                {\r
                        // 録画フォルダ等\r
-                       Matcher mc = Pattern.compile("録画フォルダ.*?(<TABLE.*?</TABLE>)\\s*<input type=hidden name=\"recFolderCount\" value=\"(\\d+?)\">",Pattern.DOTALL).matcher(d[1]);\r
+                       Matcher mc = Pattern.compile("録画フォルダ.*?(<TABLE.*?</TABLE>)\\s*<input type=hidden name=\"recFolderCount\" value=\"(\\d+?)\">",Pattern.DOTALL).matcher(res);\r
                        if ( ! mc.find() ) {\r
                                errmsg = "情報が見つかりません:"+RETVAL_KEY_RECFOLDERCOUNT;\r
                        }\r
@@ -1241,7 +1291,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                        }\r
                        \r
                        // 録画フォルダ等(ワンセグ)\r
-                       mc = Pattern.compile("partialRecFlag.*?(<TABLE.*?</TABLE>)\\s*<input type=hidden name=\"partialFolderCount\" value=\"(\\d+?)\">",Pattern.DOTALL).matcher(d[1]);\r
+                       mc = Pattern.compile("partialRecFlag.*?(<TABLE.*?</TABLE>)\\s*<input type=hidden name=\"partialFolderCount\" value=\"(\\d+?)\">",Pattern.DOTALL).matcher(res);\r
                        if ( ! mc.find() ) {\r
                                errmsg = "情報が見つかりません:"+RETVAL_KEY_PARTIALFOLDERCOUNT;\r
                        }\r
@@ -1356,7 +1406,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                }\r
                \r
                // 番組ID\r
-               if ( r.getContentId() != null ) {\r
+               if ( r.getContentId() != null && r.getContentId().length() > 0 ) {\r
                        StringBuilder dt = new StringBuilder(r.getDetail());\r
                        dt.append("■番組ID:");\r
                        dt.append(ContentIdEDCB.stripMark(r.getContentId()));\r
@@ -1389,10 +1439,29 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
        }\r
        \r
        \r
+       /*------------------------------------------------------------------------------\r
+        * 自動予約一覧の取得\r
+        *------------------------------------------------------------------------------/\r
+       \r
        /**\r
         * 自動予約一覧を取得する\r
         */\r
-       private boolean GetRdAutoReserveList(AutoReserveInfoList newAutoReserveList) {\r
+       private boolean getAutoReserveList(AutoReserveInfoList newAutoReserveList) {\r
+               if ( ! getAutorsvList(newAutoReserveList) ) {\r
+                       // 一覧が取得できなかった\r
+                       return false;\r
+               }\r
+               if ( ! getAutorsvDetailAll(newAutoReserveList) ) {\r
+                       // 詳細が取得できなかった\r
+                       return false;\r
+               }\r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * 自動予約一覧を取得する(リスト部)\r
+        */\r
+       private boolean getAutorsvList(AutoReserveInfoList newAutoReserveList) {\r
                \r
                int maxpage = 1;                        // 初期値は"1"!\r
                String firstResp = null;        // 2回読み出したくない\r
@@ -1454,7 +1523,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                                                }\r
                                                break;\r
                                        case 3: // channel\r
-                                               c.getChannels().add(CommonUtils.unEscape(mb.group(1)));\r
+                                               //c.getChannels().add(CommonUtils.unEscape(mb.group(1)));\r
                                                break;\r
                                        case 1: // mark\r
                                        case 2: // genre\r
@@ -1476,9 +1545,113 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
        }\r
        \r
        /**\r
+        * 自動予約一覧を取得する(詳細部)\r
+        */\r
+       private boolean getAutorsvDetailAll(AutoReserveInfoList newAutoReserveList) {\r
+               \r
+               String url = "http://"+getIPAddr()+":"+getPortNo()+"/autoaddepginfo.html?id=";\r
+               \r
+               int cnt = 0;\r
+               for ( AutoReserveInfo c : newAutoReserveList ) {\r
+\r
+                       ++cnt;\r
+                       \r
+                       reportProgress(String.format("自動予約詳細を取得します(%d/%d)",cnt,newAutoReserveList.size()));\r
+                       String[] d = reqGET(url+c.getId(),null);\r
+                       if (d[1] == null) {\r
+                               errmsg = "レコーダーが反応しません";\r
+                               return false;\r
+                       }\r
+                       \r
+                       if ( ! decodeAutorsvDetail(c, d[1]) ) {\r
+                               // デコードできなかった\r
+                               System.err.println("★★★ スクリプト解析まで仮置き ★★★ ");\r
+                               CommonUtils.printStackTrace();\r
+                       }\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * 自動予約詳細をデコードする\r
+        */\r
+       private boolean decodeAutorsvDetail(AutoReserveInfo c, String str) {\r
+               \r
+               String[] data = str.split("<HR>録画設定<HR>");\r
+               if ( data.length != 2 ) {\r
+                       return false;\r
+               }\r
+\r
+               // キーワード設定部\r
+               {\r
+                       // テキストボックスの場合\r
+                       {\r
+                               Matcher mb = Pattern.compile("<input type=\"text\" name=\"(.+?)\" value=\"(.*?)\" size=", Pattern.DOTALL).matcher(data[0]);\r
+                               while ( mb.find() ) {\r
+                                       if ( mb.group(1).equals("andKey") ) {\r
+                                               c.setLabel(CommonUtils.unEscape(mb.group(2)));\r
+                                               c.setKeyword(c.getLabel());\r
+                                       }\r
+                                       else if ( mb.group(1).equals("notKey") ) {\r
+                                               c.setExKeyword(CommonUtils.unEscape(mb.group(2)));\r
+                                       }\r
+                                       else if ( mb.group(1).equals("dateList") ) {\r
+                                               \r
+                                       }\r
+                                       else if ( mb.group(1).equals("chkRecDay") ) {\r
+                                               try {\r
+                                                       c.setRecordedCheckTerm(Integer.valueOf(mb.group(2)));\r
+                                                       continue;\r
+                                               }\r
+                                               catch ( NumberFormatException e) {\r
+                                                       e.printStackTrace();\r
+                                               }\r
+                                               c.setRecordedCheckTerm(6);              // デフォルトバリュー\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       // コンボボックスの場合\r
+                       {\r
+                               Matcher mb = Pattern.compile("<select name=\"(.+?)\" .*?size=\\d+?>(.*?)</select>", Pattern.DOTALL).matcher(data[0]);\r
+                               while ( mb.find() ) {\r
+                                       if ( mb.group(1).equals("contentList") ) {\r
+                                               // ジャンル\r
+                                       }\r
+                                       else if ( mb.group(1).equals("serviceList") ) {\r
+                                               \r
+                                               // 放送局\r
+                                               Matcher mc = Pattern.compile("<option value=\"(\\d+?)\" selected>", Pattern.DOTALL).matcher(mb.group(2));\r
+                                               while ( mc.find() ) {\r
+                                                       String chName = cc.getCH_CODE2WEB(mc.group(1));\r
+                                                       c.getChannels().add((chName!=null) ? chName : mc.group(1));\r
+                                               }\r
+                                       }\r
+                                       \r
+                               }\r
+                       }\r
+               }\r
+               \r
+               // 録画設定部\r
+               {\r
+                       ReserveInfo r = new ReserveInfo();\r
+                       decodeRsvDetail(r, data[1], null);\r
+                       c.setRecSetting(r);\r
+               }\r
+               \r
+               return true;\r
+       }\r
+       \r
+       \r
+       /*------------------------------------------------------------------------------\r
+        * 録画結果一覧の取得\r
+        *------------------------------------------------------------------------------/\r
+        *\r
+       /**\r
         *      録画結果一覧を取得する\r
         */\r
-       private boolean GetRdRecordedList(ArrayList<RecordedInfo> newRecordedList) {\r
+       private boolean getRecedList(ArrayList<RecordedInfo> newRecordedList) {\r
                \r
                String critDate = null;\r
                if ( newRecordedList.size() > 0 ) {\r
@@ -1523,7 +1696,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                                String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/recinfo.html?page="+page,null,thisEncoding);\r
                                response = d[1];\r
                        }\r
-                       if ( GetRdRecordedListSub(newRecordedList, response, critDate) <= 0) {\r
+                       if ( decodeRecedList(newRecordedList, response, critDate) <= 0) {\r
                                // おわったぽ\r
                                break;\r
                        }\r
@@ -1532,7 +1705,10 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                return true;\r
        }\r
        \r
-       private int GetRdRecordedListSub(ArrayList<RecordedInfo> newRecordedList, String response, String critDate) {\r
+       /**\r
+        * 録画一覧のデコード\r
+        */\r
+       private int decodeRecedList(ArrayList<RecordedInfo> newRecordedList, String response, String critDate) {\r
                \r
                int cnt = 0;\r
                \r
@@ -1620,7 +1796,10 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                return cnt;\r
        }\r
 \r
-       private boolean GetRdRecordedListDetailAll(ArrayList<RecordedInfo> newRecordedList) {\r
+       /**\r
+        * 録画詳細の取得\r
+        */\r
+       private boolean getRecedDetailAll(ArrayList<RecordedInfo> newRecordedList) {\r
                // 詳細情報を取得する\r
                int i=0;\r
                for ( RecordedInfo entry : newRecordedList ) {\r
@@ -1789,7 +1968,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                                ReserveList tmpr = new ReserveList();\r
                                tmpr.setContentId(reqr.getContentId());\r
                                setTextPresetID(tmpr, getTextPresetID(reqr));\r
-                               if ( ! GetRdReservedDetailByContentId(tmpr,0) ) {\r
+                               if ( ! getRsvDetailByContentId(tmpr,0) ) {\r
                                        errmsg = "予約ページが開けません。";\r
                                        return(false);\r
                                }\r
@@ -2222,7 +2401,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                // 更新後の情報を再取得\r
                ReserveList newr = reqr.clone();\r
                newr.setId(oldr.getId());\r
-               if ( ! GetRdReservedDetailByReserveId(newr,0) ) {\r
+               if ( ! getRsvDetailByReserveId(newr,0) ) {\r
                        errmsg = "更新後の情報を取得できませんでした。";\r
                        return null;\r
                }\r
@@ -2387,7 +2566,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                // 予約IDを試してみる(EDCBがリブートしていなければこれでOKなはず)\r
                if ( origr.getId() != null && origr.getId().length() > 0 ) {\r
                        ReserveList newr = origr.clone();\r
-                       if ( GetRdReservedDetailByReserveId(newr,0) && isEqualsTR(origr, newr, -1) ) {\r
+                       if ( getRsvDetailByReserveId(newr,0) && isEqualsTR(origr, newr, -1) ) {\r
                                //System.out.println("+-一致する予約です(予約ID直接): "+newr.getId());\r
                                return newr;\r
                        }\r
@@ -2396,7 +2575,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                // 番組IDを試してみる(重複予約されていなければこれで大丈夫なはず)\r
                if ( origr.getContentId() != null && ContentIdEDCB.isValid(origr.getContentId()) ) {\r
                        ReserveList newr = origr.clone();\r
-                       if ( GetRdReservedDetailByContentId(newr,0) && isEqualsTR(origr, newr, 0) ) {\r
+                       if ( getRsvDetailByContentId(newr,0) && isEqualsTR(origr, newr, 0) ) {\r
                                //System.out.println("+-一致する予約です(番組ID直接): "+newr.getId());\r
                                return newr;\r
                        }\r
@@ -2404,7 +2583,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
 \r
                // 一覧取得しなおし(3.17.5b)\r
                ArrayList<ReserveList> rl = new ArrayList<ReserveList>();\r
-               if ( ! GetRdReservedList(rl) ) {\r
+               if ( ! getRsvListAPI(rl) ) {\r
                        errmsg = "予約一覧の取得に失敗しました。";\r
                        return null;\r
                }\r
@@ -2484,7 +2663,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
                // 予約IDを試してみる(EDCBがリブートしていなければこれでOKなはず)\r
                if ( origr.getId() != null && origr.getId().length() > 0 ) {\r
                        ReserveList newr = origr.clone();\r
-                       if ( GetRdReservedDetailByReserveId(newr,0) && isEqualsDT(origr, newr, 0) ) {\r
+                       if ( getRsvDetailByReserveId(newr,0) && isEqualsDT(origr, newr, 0) ) {\r
                                //System.out.println("+-一致する予約です(番組ID直接): "+newr.getId());\r
                                return newr;\r
                        }\r
@@ -2492,7 +2671,7 @@ public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,C
 \r
                // 予約IDは固定ではないので再度取得しなおさないと(3.17.5b変更)\r
                ArrayList<ReserveList> rl = new ArrayList<ReserveList>();\r
-               if ( ! GetRdReservedList(rl) ) {\r
+               if ( ! getRsvListAPI(rl) ) {\r
                        errmsg = "予約一覧の取得に失敗しました。";\r
                        return null;\r
                }\r
index d2e6c52..68ee56b 100644 (file)
@@ -58,7 +58,7 @@ public class RecorderInfoList extends ArrayList<RecorderInfo> {
                        ArrayList<RecorderList> rlx = (ArrayList<RecorderList>) CommonUtils.readXML(rFileOld);\r
                        for ( RecorderList rx : rlx ) {\r
                                RecorderInfo r = new RecorderInfo();\r
-                               CommonUtils.FieldCopy(r, rx);\r
+                               FieldUtils.deepCopy(r, rx);\r
                                rl.add(r);\r
                        }\r
                }\r
index 9d21c6e..7367716 100644 (file)
@@ -203,7 +203,7 @@ public class SearchGroupList implements Iterator<SearchGroup>, Iterable<SearchGr
                        @SuppressWarnings("unchecked")\r
                        ArrayList<SearchGroup> tmpList = (ArrayList<SearchGroup>) CommonUtils.readXML(gFile);\r
                        if ( tmpList != null ) {\r
-                               CommonUtils.FieldCopy(gList, tmpList);\r
+                               FieldUtils.deepCopy(gList, tmpList);\r
                                return true;\r
                        }\r
                }\r
index a64dafd..901733a 100644 (file)
@@ -170,7 +170,7 @@ public class TVProgramList extends ArrayList<TVProgram> implements Cloneable {
        @Override\r
        public TVProgramList clone() {\r
                TVProgramList p = (TVProgramList) super.clone();\r
-               CommonUtils.FieldCopy(p, this); // ディープコピーするよ\r
+               FieldUtils.deepCopy(p, this); // ディープコピーするよ\r
                return p;\r
        }\r
 }\r
index 086f79f..c1cedf4 100644 (file)
@@ -53,7 +53,7 @@ public class TVProgramUtils implements Cloneable {
                        //p.setProgressArea(null);\r
                        //p.setChConv(null);\r
                        \r
-                       CommonUtils.FieldCopy(p, this); // ディープコピーするよ\r
+                       FieldUtils.deepCopy(p, this); // ディープコピーするよ\r
                        \r
                        p.pcenter = new ArrayList<ProgList>();\r
                        \r
diff --git a/TinyBannavi/src/tainavi/TextValueMap.java b/TinyBannavi/src/tainavi/TextValueMap.java
new file mode 100644 (file)
index 0000000..6c51c9d
--- /dev/null
@@ -0,0 +1,189 @@
+package tainavi;\r
+\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.LinkedHashMap;\r
+import java.util.Map.Entry;\r
+\r
+\r
+/**\r
+ * TextValueSetをこれで置き換える予定<BR>\r
+ * @since 3.22.2b\r
+ */\r
+public class TextValueMap extends LinkedHashMap<String,String> {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       /*******************************************************************************\r
+        * 定数\r
+        ******************************************************************************/\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * 部品\r
+        ******************************************************************************/\r
+\r
+       // 保存されない\r
+       private final String envXml;    // XML形式のファイル名\r
+       private final String label;             // GUIに表示する場合の項目名\r
+       \r
+       // 保存される\r
+       private String defaultKey;              // デフォルトのキー値\r
+       private String selectedKey;             // 選択中のキー値\r
+       \r
+       /*******************************************************************************\r
+        * getter/setter\r
+        ******************************************************************************/\r
+       \r
+       public String getDefaultKey() {\r
+               return this.defaultKey;\r
+       }\r
+       public void setDefaultKey(String s) {\r
+               this.defaultKey = s;\r
+       }\r
+\r
+       public String getSelectedKey() {\r
+               return this.selectedKey;\r
+       }\r
+       public void setSelectedKey(String s) {\r
+               this.selectedKey = s;\r
+       }\r
+\r
+       \r
+       /*******************************************************************************\r
+        * コンストラクタ\r
+        ******************************************************************************/\r
+\r
+       /**\r
+        * シリアライズ用のデフォルトコンストラクタ \r
+        */\r
+       @Deprecated\r
+       public TextValueMap() {\r
+               super();\r
+               this.label = null;\r
+               this.envXml = null;\r
+       }\r
+       \r
+       /**\r
+        * HDDレコーダ用のコンストラクタ\r
+        */\r
+       public TextValueMap(String label, String envdir, String basename, String recid, String ipaddr, String portno) {\r
+               this(label,envdir,basename,String.format("%s_%s_%s",recid,ipaddr,portno));\r
+       }\r
+       \r
+       /**\r
+        * 汎用のコンストラクタ\r
+        */\r
+       public TextValueMap(String label, String envdir, String basename, String id) {\r
+               super();\r
+               this.label = label;\r
+               this.envXml = String.format("%s%s%s.%s.xml", envdir, File.separator, basename, id);\r
+       }\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * 操作系メソッド\r
+        ******************************************************************************/\r
+\r
+       /**\r
+        * GUIで表示する項目名\r
+        */\r
+       public String getLabel() {\r
+               return this.label;\r
+       }\r
+\r
+       /**\r
+        * 保存するファイル名\r
+        */\r
+       public String getFilename() {\r
+               return this.envXml;\r
+       }\r
+       \r
+       /**\r
+        * このエントリーがデフォルトであることを示すマークを付けることのできる put()\r
+        */\r
+       public String put(String key, String value, boolean isdefault) {\r
+               String obj = super.put(key, value);\r
+               if ( isdefault ) {\r
+                       defaultKey = key;\r
+               }\r
+               return obj;\r
+       }\r
+\r
+       /**\r
+        * 使わせたくないのだよ\r
+        */\r
+       @Deprecated\r
+       @Override\r
+       public String put(String key, String value) {\r
+               return super.put(key, value);\r
+       }\r
+       \r
+       /**\r
+        * エントリーを選択する\r
+        */\r
+       public Entry<String,String> setSelectedEntry(String key) {\r
+               Entry<String,String> entry = getEntry(key);\r
+               if ( entry != null ) {\r
+                       selectedKey = entry.getKey();\r
+               }\r
+               return entry;\r
+       }\r
+       \r
+       /**\r
+        * デフォルトのエントリーを返す\r
+        */\r
+       public Entry<String,String> getDefultEntry() {\r
+               return this.getEntry(defaultKey);\r
+       }\r
+       \r
+       /**\r
+        * 選択中のエントリーを返す\r
+        */\r
+       public Entry<String,String> getSelectedEntry() {\r
+               return this.getEntry(selectedKey);\r
+       }\r
+\r
+       /**\r
+        * 指定のエントリを返す(外部からはget(key)を使えばいいので非公開)\r
+        */\r
+       private Entry<String,String> getEntry(String key) {\r
+               if ( key == null ) {\r
+                       return null;\r
+               }\r
+               for ( Entry<String,String> entry : super.entrySet() ) {\r
+                       if ( key.equals(entry.getKey()) ) {\r
+                               return entry;\r
+                       }\r
+               }\r
+               return null;\r
+       }\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * シリアライズ・デシリアライズ\r
+        ******************************************************************************/\r
+       \r
+       /**\r
+        * テキスト形式で保存する\r
+        */\r
+       public boolean save() {\r
+               if ( envXml == null ) {\r
+                       return false;\r
+               }\r
+               \r
+               return CommonUtils.writeXML(envXml, this);\r
+       }\r
+       \r
+       /**\r
+        * テキスト形式で読み込む\r
+        */\r
+       public boolean load() {\r
+               if ( envXml == null ) {\r
+                       return false;\r
+               }\r
+               \r
+               return CommonUtils.readXML(envXml, this);\r
+       }\r
+\r
+}\r
diff --git a/TinyBannavi/src/tainavi/VWHDDRecorderSelectionEvent.java b/TinyBannavi/src/tainavi/VWHDDRecorderSelectionEvent.java
deleted file mode 100644 (file)
index 37bdc6e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-package tainavi;\r
-\r
-import java.util.EventObject;\r
-import java.util.GregorianCalendar;\r
-\r
-public class VWHDDRecorderSelectionEvent extends EventObject {\r
-       \r
-       private static final long serialVersionUID = 1L;\r
-       \r
-       private final String selected;\r
-       private final HDDRecorderList recs;\r
-\r
-       public String getSelected() { return selected; }\r
-       \r
-       public HDDRecorderList getSelectedRecorderList() { return recs; }\r
-       \r
-       public VWHDDRecorderSelectionEvent(Object source, String selected, HDDRecorderList recs) {\r
-               super(source);\r
-               this.selected = selected;\r
-               this.recs = recs;\r
-       }\r
-\r
-}\r
diff --git a/TinyBannavi/src/tainavi/VWHDDRecorderSelectionListener.java b/TinyBannavi/src/tainavi/VWHDDRecorderSelectionListener.java
deleted file mode 100644 (file)
index a8e566d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-package tainavi;\r
-\r
-import java.util.EventListener;\r
-\r
-public interface VWHDDRecorderSelectionListener extends EventListener {\r
-       \r
-       // 定数\r
-       public static final String SELECTED_ALL = null;\r
-       public static final String SELECTED_PICKUP = "";\r
-       \r
-       //\r
-       public void recorderSelected(VWHDDRecorderSelectionEvent e);\r
-       \r
-       // 多分↓はよくないコード\r
-       \r
-       public String getSelectedRecorder();\r
-       \r
-       public HDDRecorderList getSelectedRecorderList();\r
-       \r
-}\r
index 34adfa4..0ad31b0 100644 (file)
@@ -4776,9 +4776,13 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                // タイトル更新\r
                setTitleBar();\r
                \r
-               // [ツールバー/レコーダ選択] 自動予約一覧\r
-               toolBar.addVWHDDRecorderSelectionListener(autores);\r
+               // [ツールバー/共通] レコーダ情報変更\r
+               toolBar.addHDDRecorderChangeListener(autores);\r
                \r
+               // [ツールバー/レコーダ選択] 自動予約一覧\r
+               toolBar.addHDDRecorderSelectionListener(autores);\r
+\r
+\r
                // レコーダ選択イベントキック\r
                toolBar.setSelectedRecorder(bounds.getSelectedRecorderId());\r
                \r
index 0d532a9..5e7ddcf 100644 (file)
@@ -1,26 +1,31 @@
 ---バグとおぼしき現象\r
 \r
 【過去ログ】検索ボックスでの日付指定と表示される日付があわない\r
+【予約ダイアログ】類似予約対応で、類似予約なしを選択しても番組IDがリセットされない\r
+【予約ダイアログ】類似予約対応で、類似予約なしを選択してもタイトルがリセットされない\r
 \r
 【レコーダ対応】RD-X5プラグインのバグ調査依頼への対応\r
+\r
+【新聞形式】類似予約を正しく抽出できない問題→予約がタイトルのみで、番組情報はタイトル+サブタイトルの場合スコアが足りなくなる →番組情報の保持の仕方を変えたので表示部をいじれば直るだろう\r
+【リスト形式】放送局別表示で、予約が多いと描画が重くなる件(AT-Xで大量に自動録画が入っているとか) →番組情報に予約情報へのリンクを張らないと改善しないだろう\r
+\r
 【録画結果一覧】TvRockに上限設定が反映されていない?\r
-【新聞形式】類似予約を正しく抽出できない問題→予約がタイトルのみで、番組情報はタイトル+サブタイトルの場合スコアが足りなくなる\r
-【新聞形式】snapshotで落ちる\r
-【予約ダイアログ】類似予約対応で番組IDの扱いが変\r
-【リスト形式】放送局別表示で、予約が多いと描画が重くなる件(AT-Xで大量に自動録画が入っているとか)\r
+\r
+【新聞形式】snapshotで落ちる →バグじゃないかも?\r
 \r
 ---優先度高\r
 \r
+【自動予約登録】EDCBとTVRockの自動予約登録編集機能の追加(~6月中旬厳守) やばい!やばい!やばい!\r
\r
 【ツールバー】「タブ内イベントでツールバーの状態を取りに行き処理」の現行ロジックを「ツールバー内のイベントで各タブの処理リスナーをキック」するように根本的に直す\r
 【その他】ContentId.class系列を全面改訂(staticをやめる!!)\r
 \r
-【過去ログ】日時ファイル単位での管理をやめる\r
+【過去ログ】日時ファイル単位での管理をやめる →放送局名の変更に対応できていないので\r
 \r
-【自動予約登録】EDCBとTVRockの自動予約登録編集機能の追加(~6月中旬厳守) \r
-【CHコンバート設定】さっさと編集を実装する\r
+【CHコンバート設定】さっさと編集を実装する →2012/11月から放置だから…\r
 【番組追跡】リピート放送検出の改善>番組追跡履歴の保存 \r
-【レコーダ対応(EDCB/TvRock)】番組IDの取得をレコーダから取得するように変更\r
-【レコーダ対応(TVRock)】UTF-8→ShiftJISに変換できない文字が化けるので、他の文字で置換するようにする\r
+【レコーダ対応(EDCB/TvRock)】番組IDの取得をレコーダから取得するように変更 →番組表がとれるので、そこから探し出すようにする\r
+【レコーダ対応(TVRock)】UTF-8→ShiftJISに変換できない文字が化けるので、他の文字で置換するようにする →ちるだとかなー\r
 \r
 【予約一覧】番組表にマッチする番組が存在しているかどうかわかるようにする(繰り返し予約で改変期に番組が終了したとかがわかるようにする)\r
 【予約一覧】録画結果一覧に正常録画済みの記録がある場合はその情報が簡単に参照できるようにする(無効化操作のときの目視確認作業を省力化)\r
@@ -30,6 +35,8 @@
 【予約ダイアログ】EPG予約未対応のレコーダの場合は番組ID取得設定になっても取得にいかないようにする? →スカパープレミアムの例外処理が現実的?\r
 【予約ダイアログ】鯛ナビの番組表とレコーダの番組表で時間が合わない番組への追従対応\r
 \r
+【キーワード検索】マッチしたエントリを新聞形式で強調表示させるオプションの追加(条件ごとの個別指定) →再放送期待age対応\r
+\r
 【キーワード検索】検索処理と表示処理の分離>過去ログ検索については完了\r
 【キーワード検索】検索履歴の保存(結果の保存までやる?)\r
 \r
@@ -71,5 +78,6 @@
 【予約一覧】タイトルソートの無視対象に[SS]を追加\r
 【予約一覧】EDCBで指定の番組と異なる番組を操作してしまうことがある→絞り込み+EXECボタンに問題 ★★★\r
 【新聞形式】日跨りイベント時に「現在放送中」が自動で翌日に切り替わらなくなった\r
+【その他】HDDRecorderListで自己フィールド生成を回避するためにmylistをstaticで宣言とかトチ狂ったコードを書いていたので修正\r
 \r
 ---以上\r