OSDN Git Service

e0e334de1c871dfc44dc7b3d09ed8dfc217706fb
[tainavi/TinyBannavi.git] / TinyBannavi / src / tainavi / PlugIn_RecRD_EDCB.java
1 package tainavi;\r
2 \r
3 import java.io.File;\r
4 import java.io.UnsupportedEncodingException;\r
5 import java.net.Authenticator;\r
6 import java.net.URLEncoder;\r
7 import java.util.ArrayList;\r
8 import java.util.Calendar;\r
9 import java.util.GregorianCalendar;\r
10 import java.util.HashMap;\r
11 import java.util.regex.Matcher;\r
12 import java.util.regex.Pattern;\r
13 \r
14 import taiSync.ReserveInfo;\r
15 \r
16 \r
17 /**\r
18  * \r
19  */\r
20 public class PlugIn_RecRD_EDCB extends HDDRecorderUtils implements HDDRecorder,Cloneable {\r
21 \r
22         @Override\r
23         public PlugIn_RecRD_EDCB clone() {\r
24                 return (PlugIn_RecRD_EDCB) super.clone();\r
25         }\r
26         \r
27         private static final String thisEncoding = "MS932";\r
28         private static final String xmlEncoding = "utf8";\r
29         \r
30         /*******************************************************************************\r
31          * 種族の特性\r
32          ******************************************************************************/\r
33 \r
34         @Override\r
35         public String getRecorderId() { return "EpgDataCap_Bon"; }\r
36         @Override\r
37         public RecType getType() { return RecType.RECORDER; }\r
38         \r
39         // 自動予約を編集できる\r
40         @Override\r
41         public boolean isEditAutoReserveSupported() { return true; }\r
42         // 自動エンコーダ選択は禁止\r
43         @Override\r
44         public boolean isAutoEncSelectEnabled() { return false; }\r
45         // 繰り返し予約はできない\r
46         @Override\r
47         public boolean isRepeatReserveSupported() { return false; }\r
48         // 番組追従が可能\r
49         @Override\r
50         public boolean isPursuesEditable() { return true; }\r
51         // タイトル自動補完はできない\r
52         @Override\r
53         public boolean isAutocompleteSupported() { return false; }\r
54         // chvalueを使っていいよ\r
55         @Override\r
56         public boolean isChValueAvailable() { return true; }\r
57         // CHコードは入力しなくていい\r
58         @Override\r
59         public boolean isChCodeNeeded() { return false; }\r
60 \r
61         /*******************************************************************************\r
62          * 予約ダイアログなどのテキストのオーバーライド\r
63          ******************************************************************************/\r
64         \r
65         @Override\r
66         public String getLabel_Audiorate() { return "予約方法"; }\r
67         @Override\r
68         public String getLabel_Folder() { return "録画モード"; }\r
69         @Override\r
70         public String getLabel_Device() { return "指定サービス対象"; }\r
71         @Override\r
72         public String getLabel_XChapter() { return "録画開始(秒前)"; }\r
73         @Override\r
74         public String getLabel_MsChapter() { return "録画終了(秒後)"; }\r
75         @Override\r
76         public String getLabel_MvChapter() { return "復帰後再起動"; }\r
77         @Override\r
78         public String getLabel_DVDCompat() { return "連続録画動作"; }\r
79         @Override\r
80         public String getLabel_LVoice() { return "ぴったり録画"; }\r
81         @Override\r
82         public String getLabel_Aspect() { return "録画後動作"; }\r
83         @Override\r
84         public String getLabel_Videorate() { return "プリセット"; }\r
85         @Override\r
86         public String getLabel_Autodel() { return "録画優先度"; }\r
87         @Override\r
88         public String getLabel_BVperf() { return "ワンセグを別ファイルに出力"; }\r
89         \r
90         @Override\r
91         public String getChDatHelp() { return\r
92                         "「レコーダの放送局名」は、予約一覧取得が正常に完了していれば設定候補がコンボボックスで選択できるようになります。"+\r
93                         "";\r
94         }\r
95         \r
96         /*******************************************************************************\r
97          * 定数\r
98          ******************************************************************************/\r
99 \r
100         private static final String ITEM_REC_MODE_DISABLE       = "無効";\r
101         \r
102         private static final String ITEM_JUST_ENABLE            = "する";\r
103 \r
104         private static final String ITEM_REC_TYPE_EPG           = "EPG";\r
105         private static final String ITEM_REC_TYPE_PROG          = "プログラム";\r
106 \r
107         private static final String ITEM_PRESETID_REG           = "予約時";\r
108 \r
109         private static final String ITEM_MARGINE_DEFAULT        = "デフォルト";\r
110         \r
111         private static final String ITEM_SERVMOCE_DEFAULT       = "デフォルト";\r
112         private static final String ITEM_SERVMOCE_SUBT          = "+字幕";\r
113         private static final String ITEM_SERVMOCE_CARO          = "+カルーセル";\r
114         private static final String ITEM_SERVMOCE_SUBTCARO      = "+字幕&カルーセル";\r
115         private static final String ITEM_SERVMOCE_NONE          = "なし";\r
116         \r
117         private static final String ITEM_YES = "する";\r
118         private static final String ITEM_NO = "しない";\r
119 \r
120         private static final String VALUE_REC_MODE_DISABLE  = "5";\r
121 \r
122         private static final String VALUE_YES  = "1";\r
123         private static final String VALUE_NO  = "0";\r
124         \r
125         private static final String VALUE_TRACE_DISABLE         = "0";\r
126         private static final String VALUE_TRACE_ENABLE          = "1";\r
127 \r
128         private static final String VALUE_REC_TYPE_EPG          = "EPG";\r
129         private static final String VALUE_REC_TYPE_PROG         = "PROGRAM";\r
130 \r
131         private static final String VALUE_PRESETID_REG          = "65535";\r
132         \r
133         private static final String VALUE_MARGINE_DEFAULT       = "FF";\r
134         \r
135         private static final String VALUE_SERVMOCE_DEFAULT      = "FF";\r
136         private static final String VALUE_SERVMOCE_SUBT         = "0-";\r
137         private static final String VALUE_SERVMOCE_CARO         = "-0";\r
138         private static final String VALUE_SERVMOCE_SUBTCARO     = "00";\r
139         private static final String VALUE_SERVMOCE_NONE         = "--";\r
140         \r
141         private static final String RETVAL_KEY_RECFOLDERCOUNT           = "recFolderCount";\r
142         private static final String RETVAL_KEY_R_RECFOLDER                      = "RrecFolder";\r
143         private static final String RETVAL_KEY_R_WRITEPLUGIN            = "RwritePlugIn";\r
144         private static final String RETVAL_KEY_R_RECNAMEPLUGIN          = "RrecNamePlugIn";\r
145         \r
146         private static final String RETVAL_KEY_PARTIALFOLDERCOUNT       = "partialFolderCount";\r
147         private static final String RETVAL_KEY_P_RECFOLDER                      = "PrecFolder";\r
148         private static final String RETVAL_KEY_P_WRITEPLUGIN            = "PwritePlugIn";\r
149         private static final String RETVAL_KEY_P_RECNAMEPLUGIN          = "PrecNamePlugIn";\r
150 \r
151         private static final String TEXT_NANSHICHO_HEADER = "臨)";\r
152         \r
153         // EPG予約の確認範囲は前後4時間まで\r
154         private static final long likersvrange = 4L*3600L*1000L;\r
155 \r
156         // HTTPリトライ回数\r
157         private static final int retryMax = 3;\r
158 \r
159         // ログ関連\r
160         \r
161         private final String MSGID = "["+getRecorderId()+"] ";\r
162         private final String ERRID = "[ERROR]"+MSGID;\r
163         private final String DBGID = "[DEBUG]"+MSGID;\r
164         \r
165         \r
166         /*******************************************************************************\r
167          * CHコード設定、エラーメッセージ\r
168          ******************************************************************************/\r
169         \r
170         @Override\r
171         public ChannelCode getChCode() {\r
172                 return cc;\r
173         }\r
174         \r
175         private ChannelCode cc = new ChannelCode(getRecorderId());\r
176         \r
177         @Override\r
178         public String getErrmsg() {\r
179                 return(errmsg);\r
180         }\r
181         \r
182         private String errmsg = "";\r
183         \r
184         /*******************************************************************************\r
185          * 部品\r
186          ******************************************************************************/\r
187 \r
188         private String rsvedFile = null;\r
189 \r
190         /*******************************************************************************\r
191          * 素のTVSではコードが読めなくなるのでラッピングしてみる\r
192          ******************************************************************************/\r
193 \r
194         private ArrayList<TextValueSet> getListPresetID()                       { return vrate; }               // プリセット\r
195         private String getTextPresetID(ReserveList r)                           { return r.getRec_mode(); }\r
196         private void setTextPresetID(ReserveList r, String text)        { r.setRec_mode(text); }\r
197         \r
198         private ArrayList<TextValueSet> getListRecMode()                        { return folder; }              // 録画モード\r
199         private String getTextRecMode(ReserveList r)                            { return r.getRec_folder(); }\r
200         private void setTextRecMode(ReserveList r, String text)         { r.setRec_folder(text); }\r
201         \r
202         private ArrayList<TextValueSet> getListPriority()                       { return autodel; }             // 優先度\r
203         private String getTextPriority(ReserveList r)                           { return r.getRec_autodel(); }\r
204         private void setTextPriority(ReserveList r, String text)        { r.setRec_autodel(text); }\r
205         \r
206         private ArrayList<TextValueSet> getListPittariFlag()            { return lvoice; }              // ぴったり(?)録画\r
207         private String getTextPittariFlag(ReserveList r)                        { return r.getRec_lvoice(); }\r
208         private void setTextPittariFlag(ReserveList r, String text)     { r.setRec_lvoice(text); }\r
209         \r
210         private ArrayList<TextValueSet> getListSuspendMode()            { return aspect; }      // 録画後動作\r
211         private String getTextSuspendMode(ReserveList r)                        { return r.getRec_aspect(); }\r
212         private void setTextSuspendMode(ReserveList r, String text)     { r.setRec_aspect(text); }\r
213         \r
214         private ArrayList<TextValueSet> getListRebootFlag()                     { return mvchapter; }   // 復帰後再起動する\r
215         private String getTextRebootFlag(ReserveList r)                         { return r.getRec_mvchapter(); }\r
216         private void setTextRebootFlag(ReserveList r, String text)      { r.setRec_mvchapter(text); }\r
217         \r
218         private ArrayList<TextValueSet> getListStartMargine()           { return xchapter; }    // 録画マージン(開始)\r
219         private String getTextStartMargine(ReserveList r)                       { return r.getRec_xchapter(); }\r
220         private void setTextStartMargine(ReserveList r, String text){ r.setRec_xchapter(text); }\r
221         \r
222         private ArrayList<TextValueSet> getListEndMargine()                     { return mschapter; }   // 録画マージン(終了)\r
223         private String getTextEndMargine(ReserveList r)                         { return r.getRec_mschapter(); }\r
224         private void setTextEndMargine(ReserveList r, String text)      { r.setRec_mschapter(text); }\r
225         \r
226         private ArrayList<TextValueSet> getListContinueRecFlag()        { return dvdcompat; }           // 連続録画動作\r
227         private String getTextContinueRecFlag(ReserveList r)            { return r.getRec_dvdcompat(); }\r
228         private void setTextContinueRecFlag(ReserveList r, String text) { r.setRec_dvdcompat(text); }\r
229         \r
230         private ArrayList<TextValueSet> getListServiceMode()            { return device; }              // 指定サービス対象データ\r
231         private String getTextServiceMode(ReserveList r)                        { return r.getRec_device(); }\r
232         private void setTextServiceMode(ReserveList r, String text)     { r.setRec_device(text); }\r
233         \r
234         private ArrayList<TextValueSet> getListTunerID()                        { return encoder; }             // 使用チューナー強制指定\r
235         private String getTextTunerID(ReserveList r)                            { return r.getTuner(); }\r
236         private void setTextTunerID(ReserveList r, String text)         { r.setTuner(text); }\r
237         \r
238         private ArrayList<TextValueSet> getListPartialRecFlag()         { return bvperf; }              // 別ファイルに同時出力する\r
239         private String getTextPartialRecFlag(ReserveList r)                     { return r.getRec_bvperf(); }\r
240         private void setTextPartialRecFlag(ReserveList r, String text)  { r.setRec_bvperf(text); }\r
241         \r
242         private ArrayList<TextValueSet> getListRecType()                        { return arate; }               // 予約方式 ★鯛ナビ独自\r
243         private String getTextRecType(ReserveList r)                            { return r.getRec_audio(); }\r
244         private void setTextRecType(ReserveList r, String text)         { r.setRec_audio(text); }\r
245         \r
246         private ArrayList<TextValueSet> getListChValue()                        { return chvalue; }             // CH番号 ★鯛ナビ独自\r
247         //private String getTextChValue(ReserveList r)                          { return null; }\r
248         \r
249         private ArrayList<TextValueSet> getListChType()                         { return chtype; }              // CH種別 ★鯛ナビ独自\r
250         //private String getTextChType(ReserveList r)                                   { return null; }\r
251         \r
252         private void setListPresetID(ArrayList<TextValueSet> tvs)               { ArrayList<TextValueSet> o = getListPresetID();                o.clear(); o.addAll(tvs); }\r
253         private void setListRecMode(ArrayList<TextValueSet> tvs)                { ArrayList<TextValueSet> o = getListRecMode();                 o.clear(); o.addAll(tvs); }\r
254         private void setListPriority(ArrayList<TextValueSet> tvs)               { ArrayList<TextValueSet> o = getListPriority();                o.clear(); o.addAll(tvs); }\r
255         private void setListPittariFlag(ArrayList<TextValueSet> tvs)    { ArrayList<TextValueSet> o = getListPittariFlag();             o.clear(); o.addAll(tvs); }\r
256         private void setListSuspendMode(ArrayList<TextValueSet> tvs)    { ArrayList<TextValueSet> o = getListSuspendMode();             o.clear(); o.addAll(tvs); }\r
257         //private void setListRebootFlag(ArrayList<TextValueSet> tvs)           { ArrayList<TextValueSet> o = getListRebootFlag();              o.clear(); o.addAll(tvs); }\r
258         //private void setListStartMargine(ArrayList<TextValueSet> tvs) { ArrayList<TextValueSet> o = getListStartMargine();    o.clear(); o.addAll(tvs); }\r
259         //private void setListEndMargine(ArrayList<TextValueSet> tvs)           { ArrayList<TextValueSet> o = getListEndMargine();              o.clear(); o.addAll(tvs); }\r
260         //private void setListContinueRecFlag(ArrayList<TextValueSet> tvs){ ArrayList<TextValueSet> o = getListContinueRecFlag();       o.clear(); o.addAll(tvs); }\r
261         private void setListTunerID(ArrayList<TextValueSet> tvs)                { ArrayList<TextValueSet> o = getListTunerID();                 o.clear(); o.addAll(tvs); }\r
262         //private void setListPartialRecFlag(ArrayList<TextValueSet> tvs)       { ArrayList<TextValueSet> o = getListPartialRecFlag();  o.clear(); o.addAll(tvs); }\r
263         //private void setListRecType(ArrayList<TextValueSet> tvs)              { ArrayList<TextValueSet> o = getListRecType();                 o.clear(); o.addAll(tvs); }\r
264         private void setListChValue(ArrayList<TextValueSet> tvs)                { ArrayList<TextValueSet> o = getListChValue();                 o.clear(); o.addAll(tvs); }\r
265         private void setListChType(ArrayList<TextValueSet> tvs)                 { ArrayList<TextValueSet> o = getListChType();                  o.clear(); o.addAll(tvs); }\r
266 \r
267         /*******************************************************************************\r
268          * コンストラクタ\r
269          ******************************************************************************/\r
270         \r
271         public PlugIn_RecRD_EDCB() {\r
272                 setIPAddr("127.0.0.1(サンプル)");\r
273                 setPortNo("5510(サンプル)");\r
274                 setUser("IDとPASSはダミーで結構です");\r
275                 setPasswd("********");\r
276         }\r
277 \r
278         /*******************************************************************************\r
279          * チャンネルリモコン機能\r
280          ******************************************************************************/\r
281         \r
282         @Override\r
283         public boolean ChangeChannel(String Channel) {\r
284                 // 何もない\r
285                 return false;\r
286         }\r
287         \r
288         /*\r
289         @Override\r
290         public void wakeup() {\r
291         }\r
292         */\r
293         \r
294         @Override\r
295         public void shutdown() {\r
296         }\r
297 \r
298         \r
299         /*******************************************************************************\r
300          * レコーダーから予約一覧を取得する\r
301          ******************************************************************************/\r
302         \r
303         @Override\r
304         public boolean GetRdSettings(boolean force) {\r
305                 \r
306                 System.out.println("レコーダの各種設定情報を取得します.");\r
307                 \r
308                 errmsg = "";\r
309                 \r
310                 /*\r
311                  *  CHコード設定\r
312                  */\r
313                 \r
314                 cc.load(force);\r
315                 replaceChNames(cc);             // これは予約一覧取得からの場合は無駄な処理になるが、GetRdSettings単体呼び出しなら意味がある\r
316                 \r
317                 /*\r
318                  *  選択肢集団\r
319                  */\r
320                 \r
321                 final String presetIdTFile      = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "presetId", getIPAddr(), getPortNo());\r
322                 final String recModeTFile       = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "recMode", getIPAddr(), getPortNo());\r
323                 final String prioTFile          = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "priority", getIPAddr(), getPortNo());\r
324                 final String pittariTFile       = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "pittari", getIPAddr(), getPortNo());\r
325                 final String suspModeTFile      = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "suspendMode", getIPAddr(), getPortNo());\r
326                 final String tunerIdTFile       = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "tunerId", getIPAddr(), getPortNo());\r
327                 final String chTypeTFile        = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "chType", getIPAddr(), getPortNo());\r
328                 final String chValueTFile       = String.format("%s%srs_%s.%s.%s_%s.xml", "env", File.separator, getRecorderId(), "chValue", getIPAddr(), getPortNo());\r
329 \r
330                 // ハードコーディングな選択肢の面々\r
331                 setSettingNoYes(getListRebootFlag());\r
332                 setSettingRecMargin(getListStartMargine());\r
333                 setSettingRecMargin(getListEndMargine());\r
334                 setSettingServiceMode(getListServiceMode());\r
335                 setSettingNoYes(getListContinueRecFlag());\r
336                 setSettingNoYes(getListPartialRecFlag());\r
337                 setSettingRecType(getListRecType());\r
338         \r
339                 if ( force == false ) {\r
340                         /*\r
341                          *  キャッシュから読み出し\r
342                          */\r
343                         setListPresetID(TVSload(presetIdTFile));\r
344                         setListRecMode(TVSload(recModeTFile));\r
345                         setListPriority(TVSload(prioTFile));\r
346                         setListPittariFlag(TVSload(pittariTFile));\r
347                         setListSuspendMode(TVSload(suspModeTFile));\r
348                         setListTunerID(TVSload(tunerIdTFile));\r
349                         setListChValue(TVSload(chValueTFile));\r
350                         setListChType(TVSload(chTypeTFile));\r
351                 }\r
352                 else {\r
353                         /*\r
354                          *  レコーダから読み出し\r
355                          */\r
356                         \r
357                         // おまじない\r
358                         Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
359                         \r
360                         // (1)録画設定の取得\r
361                         {\r
362                                 reportProgress("録画設定を取得します.");\r
363                                 String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/addprogres.html",null);\r
364                                 //String hdr = d[0];\r
365                                 String res = d[1];\r
366                                 \r
367                                 if ( res == null ) {\r
368                                         errmsg = "レコーダーが反応しません";\r
369                                         return false;\r
370                                 }\r
371                                 \r
372                                 ArrayList<TextValueSet> tvs = new ArrayList<TextValueSet>();\r
373                                 ArrayList<TextValueSet> tvs2 = new ArrayList<TextValueSet>();\r
374                                 \r
375                                 // (1-1)プリセット\r
376                                 setSettingEtc(tvs,"presetID",0,res);\r
377                                 add2tvs(tvs, ITEM_PRESETID_REG, VALUE_PRESETID_REG);    // なんつーか\r
378                                 TVSsave(tvs, presetIdTFile);\r
379                                 setListPresetID(tvs);\r
380         \r
381                                 // (1-2)録画モード\r
382                                 setSettingEtc(tvs,"recMode",0,res);\r
383                                 for ( TextValueSet o : tvs ) {\r
384                                         if ( o.getText().equals(ITEM_REC_MODE_DISABLE) ) {\r
385                                                 tvs.remove(o);\r
386                                                 break;\r
387                                         }\r
388                                 }\r
389                                 TVSsave(tvs, recModeTFile);\r
390                                 setListRecMode(tvs);\r
391                                 \r
392                                 // (1-12)録画優先度\r
393                                 setSettingEtc(tvs, "priority", 0, res);\r
394                                 TVSsave(tvs, prioTFile);\r
395                                 setListPriority(tvs);\r
396                                 \r
397                                 // (1-11)ぴったり\r
398                                 setSettingEtc(tvs,"pittariFlag",0,res);\r
399                                 TVSsave(tvs, pittariTFile);\r
400                                 setListPittariFlag(tvs);\r
401                                 \r
402                                 // (1-6)録画後動作\r
403                                 setSettingEtc(tvs,"suspendMode",0,res);\r
404                                 TVSsave(tvs, suspModeTFile);\r
405                                 setListSuspendMode(tvs);\r
406                                 \r
407                                 // (1-4)エンコーダ\r
408                                 setSettingEtc(tvs,"tunerID",0,res);\r
409                                 TVSsave(tvs, tunerIdTFile);\r
410                                 setListTunerID(tvs);\r
411                                 \r
412                                 // (1-5)チャンネル\r
413                                 setSettingChCodeValue(tvs,tvs2,"serviceID",res);\r
414                                 TVSsave(tvs, chValueTFile);\r
415                                 TVSsave(tvs2, chTypeTFile);\r
416                                 setListChValue(tvs);\r
417                                 setListChType(tvs);\r
418                         }\r
419                 }\r
420                 \r
421                 // ちゃんと設定を取得できているよね?\r
422                 return (getListTunerID().size()>0 && getListChValue().size()>0 && getListPresetID().size()>0);\r
423         }\r
424         \r
425         /**\r
426          *      レコーダーから予約一覧を取得する \r
427          */\r
428         @Override\r
429         public boolean GetRdReserve(boolean force) {\r
430         \r
431                 System.out.println("レコーダから予約一覧を取得します("+force+")");\r
432                 \r
433                 errmsg = "";\r
434                 \r
435                 // 予約情報キャッシュ保存先ファイル名\r
436                 rsvedFile = String.format("%s%s%s.%s_%s_%s.xml", "env", File.separator, "reserved", getIPAddr(), getPortNo(), getRecorderId());\r
437 \r
438                 // おまじない\r
439                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
440                 \r
441                 File f = new File(rsvedFile);\r
442                 if ( force == false && f.exists() ) {\r
443                         // キャッシュから読み出し(予約一覧)\r
444                         setReserves(ReservesFromFile(rsvedFile));\r
445                         replaceChNames(cc);\r
446                         if (getDebug()) ShowReserves(getReserves());\r
447 \r
448                         return true;\r
449                 }\r
450                 \r
451                 // レコーダから読み出し(予約一覧)\r
452                 ArrayList<ReserveList> newReserveList = new ArrayList<ReserveList>();\r
453                 if ( ! getRsvListAPI(newReserveList) ) {\r
454                         return(false);\r
455                 }\r
456                 \r
457                 // 既存予約一覧からの情報引き継ぎ\r
458                 copyAttributesAllList(getReserves(), newReserveList);\r
459                 \r
460                 // 保存\r
461                 setReserves(newReserveList);\r
462                 ReservesToFile(getReserves(), rsvedFile);       // キャッシュに保存\r
463                 \r
464                 // 録画済みフラグを立てる(録画結果一覧→予約一覧)\r
465                 setRecordedFlag();\r
466                 \r
467                 ShowReserves(getReserves());\r
468                 \r
469                 return true;\r
470         }\r
471         \r
472         /**\r
473          * CHコードを置き換えよう(EDCBの場合はCODE2WEB)\r
474          */\r
475         private void replaceChNames(ChannelCode cc) {\r
476                 for ( ReserveList r : getReserves() ) {\r
477                         r.setCh_name(cc.getCH_CODE2WEB(r.getChannel()));\r
478                 }\r
479         }\r
480         \r
481         /**\r
482          *      レコーダーから自動予約一覧を取得する \r
483          */\r
484         @Override\r
485         public boolean GetRdAutoReserve(boolean force) {\r
486         \r
487                 System.out.println("レコーダから自動予約一覧を取得します("+force+")");\r
488                 \r
489                 errmsg = "";\r
490                 \r
491                 AutoReserveInfoList newList = new AutoReserveInfoList(Env.envDir,null,getRecorderId(),getIPAddr(),getPortNo());\r
492                 \r
493                 if ( ! force && newList.exists() ) {\r
494                         // 既存のファイルがあれば読み出す\r
495                         if ( newList.load() ) {\r
496                                 setAutoReserves(newList);\r
497                                 return true;\r
498                         }\r
499                         \r
500                         // ★★★ログだせよ!\r
501                         \r
502                         return false;   // 読めなかったよ\r
503                 }\r
504                 \r
505                 // おまじない\r
506                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
507                 \r
508                 // リモートから取得\r
509                 if ( ! getAutoReserveList(newList) ) {\r
510                         if ( newList.exists() ) {\r
511                                 // 過去に取得したことがあるなら通信エラーとして処理\r
512                                 return false;\r
513                         }\r
514                         else {\r
515                                 // 過去に取得したことがあるないのでスキップ扱い(にしないと移行時に録画結果一覧が表示されないよね)\r
516                                 return true;\r
517                         }\r
518                 }\r
519                 \r
520                 setAutoReserves(newList);\r
521                 \r
522                 if ( ! newList.save() ) {\r
523                         // ★★★ログだせよ!\r
524                 }\r
525                 \r
526                 return true;\r
527         }\r
528         \r
529         /**\r
530          *      レコーダーから録画結果一覧を取得する \r
531          * @see #GetRdSettings(boolean)\r
532          */\r
533         @Override\r
534         public boolean GetRdRecorded(boolean force) {\r
535                 \r
536                 // おまじない\r
537                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
538                 \r
539                 System.out.println("レコーダから録画結果一覧を取得します("+force+"): "+getRecorderId()+"("+getIPAddr()+":"+getPortNo()+")");\r
540                 \r
541                 String recedFile = String.format("%s%s%s.%s_%s_%s.xml", "env", File.separator, "recorded", getIPAddr(), getPortNo(), getRecorderId());\r
542                 \r
543                 // 既存のログをチェック\r
544                 ArrayList<RecordedInfo> newRecordedList = RecordedFromFile(recedFile);\r
545                 \r
546                 File f = new File(recedFile);\r
547                 if ( ! force && f.exists() ) {\r
548                         \r
549                         // キャッシュから読み出し(録画結果一覧)\r
550                         setRecorded(newRecordedList);\r
551                         if (getDebug()) ShowRecorded(getRecorded());\r
552         \r
553                         // 録画済みフラグを立てる(録画結果一覧→予約一覧)\r
554                         setRecordedFlag();\r
555                 \r
556                         return true;\r
557                 }\r
558                 \r
559                 if ( ! getRecedList(newRecordedList) ) {\r
560                         return false;\r
561                 }\r
562                 if ( ! getRecedDetailAll(newRecordedList) ) {\r
563                         return false;\r
564                 }\r
565                 setRecorded(newRecordedList);                           // 置き換え\r
566                 RecordedToFile(getRecorded(), recedFile);       // キャッシュに保存\r
567                 \r
568                 // 録画済みフラグを立てる(録画結果一覧→予約一覧)\r
569                 setRecordedFlag();\r
570                 \r
571                 ShowRecorded(getRecorded());\r
572 \r
573                 return true;\r
574         }\r
575         \r
576         \r
577         /*------------------------------------------------------------------------------\r
578          * 予約一覧の取得\r
579          *------------------------------------------------------------------------------/\r
580         \r
581         /**\r
582          * 予約一覧+詳細の取得【API版】\r
583          */\r
584         private boolean getRsvListAPI(ArrayList<ReserveList> newReserveList) {\r
585                 \r
586                 // RDから予約一覧を取り出す\r
587                 String response="";\r
588                 {\r
589                         reportProgress("予約一覧を取得します.");\r
590                         String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/api/EnumReserveInfo",null,xmlEncoding);\r
591                         response = d[1];\r
592                         \r
593                         if (response == null) {\r
594                                 errmsg = "レコーダーが反応しません";\r
595                                 return(false);\r
596                         }\r
597                 }\r
598                 \r
599                 Matcher ma = Pattern.compile("<reserveinfo>(.+?)</reserveinfo>", Pattern.DOTALL).matcher(response);\r
600                 while ( ma.find() ) {\r
601                         String id = null;\r
602                         String title = null;\r
603                         GregorianCalendar cal = null;\r
604                         Integer hh = null;\r
605                         Integer mm = null;\r
606                         Integer length = null;\r
607                         Integer onid = null;\r
608                         Integer tsid = null;\r
609                         Integer sid = null;\r
610                         Integer evid = null;            // 65536:プログラム予約\r
611                         String comment = null;\r
612                         Integer overlapMode = null;\r
613                         \r
614                         Integer recMode = null;\r
615                         Integer priority = null;\r
616                         Integer tuijyuuFlag = null;\r
617                         Integer serviceMode = null;\r
618                         Integer pittariFlag = null;\r
619                         Integer suspendMode = null;\r
620                         Integer rebootFlag = null;\r
621                         Integer useMargineFlag = null;\r
622                         Integer startMargine = null;\r
623                         Integer endMargine = null;\r
624                         Integer continueRecFlag = null;\r
625                         Integer partialRecFlag = null;\r
626                         Integer tunerID = null;\r
627                         \r
628                         String batFilePath = null;\r
629                         \r
630                         int recFolderCount = 0;\r
631                         ArrayList<String> rRecFolder = new ArrayList<String>();\r
632                         ArrayList<String> rWritePlugIn = new ArrayList<String>();\r
633                         ArrayList<String> rRecNamePlugIn = new ArrayList<String>();\r
634                         \r
635                         int partialFolderCount = 0;\r
636                         ArrayList<String> pRecFolder = new ArrayList<String>();\r
637                         ArrayList<String> pWritePlugIn = new ArrayList<String>();\r
638                         ArrayList<String> pRecNamePlugIn = new ArrayList<String>();\r
639                         \r
640                         ArrayList<String> recFileNameList = new ArrayList<String>();\r
641 \r
642                         Matcher mb = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(ma.group(1));\r
643                         while ( mb.find() ) {\r
644                                 /*\r
645                                  * 解析\r
646                                  */\r
647                                 \r
648                                 // 基本情報\r
649                                 if ( mb.group(1).equals("ID") ) {\r
650                                         id = mb.group(2);\r
651                                 }\r
652                                 else if ( mb.group(1).equals("title") ) {\r
653                                         title = CommonUtils.unEscape(mb.group(2));\r
654                                 }\r
655                                 else if ( mb.group(1).equals("startDate") ) {\r
656                                         Matcher mc = Pattern.compile("^(\\d+)/(\\d+)/(\\d+)").matcher(mb.group(2));\r
657                                         if ( mc.find() ) {\r
658                                                 cal = CommonUtils.getCalendar(String.format("%04d/%02d/%02d",Integer.valueOf(mc.group(1)),Integer.valueOf(mc.group(2)),Integer.valueOf(mc.group(3))));\r
659                                         }\r
660                                 }\r
661                                 else if ( mb.group(1).equals("startTime") ) {\r
662                                         Matcher mc = Pattern.compile("^(\\d+):(\\d+)").matcher(mb.group(2));\r
663                                         if ( mc.find() ) {\r
664                                                 hh = Integer.valueOf(mc.group(1));\r
665                                                 mm = Integer.valueOf(mc.group(2));\r
666                                         }\r
667                                 }\r
668                                 else if ( mb.group(1).equals("duration") ) {\r
669                                         length = Integer.valueOf(mb.group(2))/60;\r
670                                 }\r
671                                 else if ( mb.group(1).equals("ONID") ) {\r
672                                         onid = Integer.valueOf(mb.group(2));\r
673                                 }\r
674                                 else if ( mb.group(1).equals("TSID") ) {\r
675                                         tsid = Integer.valueOf(mb.group(2));\r
676                                 }\r
677                                 else if ( mb.group(1).equals("SID") ) {\r
678                                         sid = Integer.valueOf(mb.group(2));\r
679                                 }\r
680                                 else if ( mb.group(1).equals("eventID") ) {\r
681                                         evid = Integer.valueOf(mb.group(2));\r
682                                 }\r
683                                 else if ( mb.group(1).equals("comment") ) {\r
684                                         comment = CommonUtils.unEscape(mb.group(2));\r
685                                 }\r
686                                 else if ( mb.group(1).equals("overlapMode") ) {\r
687                                         overlapMode = Integer.valueOf(mb.group(2));\r
688                                 }\r
689                                 else if ( mb.group(1).equals("recsetting") ) {\r
690                                         // 録画設定\r
691                                         Matcher mc = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(mb.group(2));\r
692                                         while ( mc.find() ) {\r
693                                                 if ( mc.group(1).equals("recMode") ) {\r
694                                                         recMode = Integer.valueOf(mc.group(2));\r
695                                                 }\r
696                                                 else if ( mc.group(1).equals("priority") ) {\r
697                                                         priority = Integer.valueOf(mc.group(2));\r
698                                                 }\r
699                                                 else if ( mc.group(1).equals("tuijyuuFlag") ) {\r
700                                                         tuijyuuFlag = Integer.valueOf(mc.group(2));\r
701                                                 }\r
702                                                 else if ( mc.group(1).equals("serviceMode") ) {\r
703                                                         serviceMode = Integer.valueOf(mc.group(2));\r
704                                                 }\r
705                                                 else if ( mc.group(1).equals("pittariFlag") ) {\r
706                                                         pittariFlag = Integer.valueOf(mc.group(2));\r
707                                                 }\r
708                                                 else if ( mc.group(1).equals("batFilePath") ) {\r
709                                                         batFilePath = mc.group(2);\r
710                                                 }\r
711                                                 else if ( mc.group(1).equals("suspendMode") ) {\r
712                                                         suspendMode = Integer.valueOf(mc.group(2));\r
713                                                 }\r
714                                                 else if ( mc.group(1).equals("rebootFlag") ) {\r
715                                                         rebootFlag = Integer.valueOf(mc.group(2));\r
716                                                 }\r
717                                                 else if ( mc.group(1).equals("useMargineFlag") ) {\r
718                                                         useMargineFlag = Integer.valueOf(mc.group(2));\r
719                                                 }\r
720                                                 else if ( mc.group(1).equals("startMargine") ) {\r
721                                                         startMargine = Integer.valueOf(mc.group(2));\r
722                                                 }\r
723                                                 else if ( mc.group(1).equals("endMargine") ) {\r
724                                                         endMargine = Integer.valueOf(mc.group(2));\r
725                                                 }\r
726                                                 else if ( mc.group(1).equals("continueRecFlag") ) {\r
727                                                         continueRecFlag = Integer.valueOf(mc.group(2));\r
728                                                 }\r
729                                                 else if ( mc.group(1).equals("partialRecFlag") ) {\r
730                                                         partialRecFlag = Integer.valueOf(mc.group(2));\r
731                                                 }\r
732                                                 else if ( mc.group(1).equals("tunerID") ) {\r
733                                                         tunerID = Integer.valueOf(mc.group(2));\r
734                                                 }\r
735                                                 else if ( mc.group(1).equals("recFolderList") ) {\r
736                                                         Matcher md = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(mc.group(2));\r
737                                                         while ( md.find() ) {\r
738                                                                 if ( md.group(1).equals("recFolderInfo") ) {\r
739                                                                         recFolderCount++;\r
740                                                                         Matcher me = Pattern.compile("<(.+?)>(.*?)</\\1>", Pattern.DOTALL).matcher(md.group(2));\r
741                                                                         while ( me.find() ) {\r
742                                                                                 if ( me.group(1).equals("recFolder") ) {\r
743                                                                                         rRecFolder.add(me.group(2));\r
744                                                                                 }\r
745                                                                                 else if ( me.group(1).equals("writePlugIn") ) {\r
746                                                                                         rWritePlugIn.add(me.group(2));\r
747                                                                                 }\r
748                                                                                 else if ( me.group(1).equals("recNamePlugIn") ) {\r
749                                                                                         rRecNamePlugIn.add(me.group(2));\r
750                                                                                 }\r
751                                                                         }\r
752                                                                 }\r
753                                                         }\r
754                                                 }\r
755                                                 else if ( mc.group(1).equals("partialRecFolder") ) {\r
756                                                         Matcher md = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(mc.group(2));\r
757                                                         while ( md.find() ) {\r
758                                                                 if ( md.group(1).equals("recFolderInfo") ) {\r
759                                                                         partialFolderCount++;\r
760                                                                         Matcher me = Pattern.compile("<(.+?)>(.*?)</\\1>", Pattern.DOTALL).matcher(md.group(2));\r
761                                                                         while ( me.find() ) {\r
762                                                                                 if ( me.group(1).equals("recFolder") ) {\r
763                                                                                         pRecFolder.add(me.group(2));\r
764                                                                                 }\r
765                                                                                 else if ( me.group(1).equals("writePlugIn") ) {\r
766                                                                                         pWritePlugIn.add(me.group(2));\r
767                                                                                 }\r
768                                                                                 else if ( me.group(1).equals("recNamePlugIn") ) {\r
769                                                                                         pRecNamePlugIn.add(me.group(2));\r
770                                                                                 }\r
771                                                                         }\r
772                                                                 }\r
773                                                         }\r
774                                                 }\r
775                                         }\r
776                                 }\r
777                                 else if ( mb.group(1).equals("recFileNameList") ) {\r
778                                         Matcher mc = Pattern.compile("<(.+?)>(.+?)</\\1>", Pattern.DOTALL).matcher(mb.group(2));\r
779                                         while ( mc.find() ) {\r
780                                                 if ( mc.group(1).equals("name") ) {\r
781                                                         recFileNameList.add(mc.group(2));\r
782                                                 }\r
783                                         }\r
784                                 }\r
785                         }\r
786                         \r
787                         /*\r
788                          * 生成\r
789                          */\r
790                         \r
791                         ReserveList r = new ReserveList();\r
792                         \r
793                         r.setId(getUniqId(id));\r
794                         r.setTitle(title);\r
795                         r.setTitlePop(TraceProgram.replacePop(title));\r
796                         \r
797                         String chid = ContentIdEDCB.getChId(onid, tsid, sid);\r
798                         String edcbid = ContentIdEDCB.getContentId(chid, evid);\r
799                         String contentid = ContentIdEDCB.stripMark(edcbid);\r
800 \r
801                         {\r
802                                 StringBuilder dt = new StringBuilder("■予約状況:");\r
803                                 if ( evid != 0 && evid != 65535 ) {\r
804                                         // EPG予約\r
805                                         r.setContentId(edcbid);\r
806                                         setTextRecType(r,ITEM_REC_TYPE_EPG);\r
807                                         //\r
808                                         if ( comment != null && comment.contains("EPG自動予約") ) {\r
809                                                 dt.append(comment);\r
810                                                 r.setAutoreserved(true);\r
811                                         }\r
812                                         else {\r
813                                                 dt.append("EPG手動予約");\r
814                                                 r.setAutoreserved(false);\r
815                                         }\r
816                                 }\r
817                                 else {\r
818                                         // プログラム予約\r
819                                         r.setContentId(null);\r
820                                         setTextRecType(r,ITEM_REC_TYPE_PROG);\r
821                                         //\r
822                                         dt.append("プログラム予約");\r
823                                         r.setAutoreserved(false);\r
824                                 }\r
825                                 dt.append("\n");\r
826                                 r.setDetail(dt.toString());             // 初期化\r
827                         }\r
828                         \r
829                         r.setChannel(String.valueOf(Long.decode("0x"+chid)));\r
830                         r.setCh_name(cc.getCH_CODE2WEB(r.getChannel()));\r
831                         \r
832                         r.setRec_pattern(CommonUtils.getDate(cal));\r
833                         r.setRec_pattern_id(11);\r
834                         cal.set(Calendar.HOUR_OF_DAY, hh);\r
835                         cal.set(Calendar.MINUTE, mm);\r
836                         r.setAhh(String.format("%02d", cal.get(Calendar.HOUR_OF_DAY)));\r
837                         r.setAmm(String.format("%02d", cal.get(Calendar.MINUTE)));\r
838                         cal.add(Calendar.MINUTE,length);\r
839                         r.setZhh(String.format("%02d", cal.get(Calendar.HOUR_OF_DAY)));\r
840                         r.setZmm(String.format("%02d", cal.get(Calendar.MINUTE)));\r
841                         r.setRec_nextdate(CommonUtils.getNextDate(r));\r
842                         r.setRec_min(CommonUtils.getRecMin(r.getAhh(), r.getAmm(), r.getZhh(), r.getZmm()));\r
843                         getStartEndDateTime(r);\r
844                         \r
845                         // 予約実行とチューナー不足\r
846                         {\r
847                                 String text = value2text(getListRecMode(),String.valueOf(recMode));\r
848                                 setTextRecMode(r, text);\r
849                                 if ( text.equals("") ) {\r
850                                         r.setExec(false);\r
851                                         r.setTunershort(false);\r
852                                 }\r
853                                 else {\r
854                                         r.setExec(true);\r
855                                         r.setTunershort(overlapMode!=0);\r
856                                 }\r
857                         }\r
858                         \r
859                         // プリセット(予約一覧からとれる情報は常に「予約時」)\r
860                         setTextPresetID(r, value2text(getListPresetID(),VALUE_PRESETID_REG));\r
861                         \r
862                         // チューナー\r
863                         setTextTunerID(r, value2text(getListTunerID(),String.valueOf(tunerID)));\r
864                         \r
865                         // 録画後動作\r
866                         setTextSuspendMode(r, value2text(getListSuspendMode(),String.valueOf(suspendMode)));\r
867 \r
868                         // 追従\r
869                         r.setPursues(VALUE_YES.equals(String.valueOf(tuijyuuFlag)));\r
870                         \r
871                         // ぴったり\r
872                         setTextPittariFlag(r, value2text(getListPittariFlag(),String.valueOf(pittariFlag)));\r
873                         \r
874                         // 録画優先度\r
875                         setTextPriority(r, value2text(getListPriority(),String.valueOf(priority)));\r
876                         \r
877                         // 連続録画動作\r
878                         if ( VALUE_YES.equals(String.valueOf(continueRecFlag)) ) {\r
879                                 setTextContinueRecFlag(r, ITEM_YES);\r
880                         }\r
881                         else {\r
882                                 setTextContinueRecFlag(r, ITEM_NO);\r
883                         }\r
884                         \r
885                         // 復帰後動作\r
886                         if ( VALUE_YES.equals(String.valueOf(rebootFlag)) ) {\r
887                                 setTextRebootFlag(r, ITEM_YES);\r
888                         }\r
889                         else {\r
890                                 setTextRebootFlag(r, ITEM_NO);\r
891                         }\r
892                         \r
893                         // 指定サービス対象データ\r
894                         if ( serviceMode == 0x00 ) {\r
895                                 setTextServiceMode(r, ITEM_SERVMOCE_DEFAULT);\r
896                         }\r
897                         else if ( serviceMode == 0x01 ) {\r
898                                 setTextServiceMode(r, ITEM_SERVMOCE_NONE);\r
899                         }\r
900                         else if ( serviceMode == 0x11 ) {\r
901                                 setTextServiceMode(r, ITEM_SERVMOCE_SUBT);\r
902                         }\r
903                         else if ( serviceMode == 0x21 ) {\r
904                                 setTextServiceMode(r, ITEM_SERVMOCE_CARO);\r
905                         }\r
906                         else if ( serviceMode == 0x31 ) {\r
907                                 setTextServiceMode(r, ITEM_SERVMOCE_SUBTCARO);\r
908                         }\r
909                         \r
910                         // 録画マージン\r
911                         if ( useMargineFlag == 0 ) {\r
912                                 setTextStartMargine(r, ITEM_MARGINE_DEFAULT);\r
913                                 setTextEndMargine(r, ITEM_MARGINE_DEFAULT);\r
914                         }\r
915                         else {\r
916                                 setTextStartMargine(r, String.valueOf(startMargine));\r
917                                 setTextEndMargine(r, String.valueOf(endMargine));\r
918                         }\r
919                         \r
920                         // 別ファイルに同時出力する\r
921                         if ( VALUE_YES.equals(String.valueOf(partialRecFlag)) ) {\r
922                                 setTextPartialRecFlag(r, ITEM_YES);\r
923                         }\r
924                         else {\r
925                                 setTextPartialRecFlag(r, ITEM_NO);\r
926                         }\r
927                         \r
928                         // 録画後実行bat\r
929                         if ( batFilePath != null ) {\r
930                                 StringBuilder dt = new StringBuilder(r.getDetail());\r
931                                 dt.append("■録画後実行bat:");\r
932                                 dt.append(batFilePath);\r
933                                 dt.append("\n");\r
934                                 r.setDetail(dt.toString());\r
935                         }\r
936                         \r
937                         // オプショナル\r
938                         r.getHidden_params().put(RETVAL_KEY_RECFOLDERCOUNT, String.valueOf(recFolderCount));\r
939                         if ( recFolderCount > 0 && rRecFolder.size() >= recFolderCount && rWritePlugIn.size() >= recFolderCount && rRecNamePlugIn.size() >= recFolderCount ) {\r
940                                 StringBuilder dt = new StringBuilder(r.getDetail());\r
941                                 StringBuilder rf = new StringBuilder();\r
942                                 StringBuilder wp = new StringBuilder();\r
943                                 StringBuilder rp = new StringBuilder();\r
944                                 for ( int i=0; i<recFolderCount; i++ ) {\r
945                                         dt.append("■録画フォルダ・出力PlugIn・ファイル名PlugIn(");\r
946                                         dt.append(String.valueOf(i+1));\r
947                                         dt.append("):");\r
948                                         dt.append(rRecFolder.get(i));\r
949                                         dt.append(" / ");\r
950                                         dt.append(rWritePlugIn.get(i));\r
951                                         dt.append(" / ");\r
952                                         dt.append(rRecNamePlugIn.get(i));\r
953                                         dt.append("\n");\r
954                                         \r
955                                         rf.append(rRecFolder.get(i));\r
956                                         rf.append("\t");\r
957                                         \r
958                                         wp.append(rWritePlugIn.get(i));\r
959                                         wp.append("\t");\r
960                                         \r
961                                         rp.append(rRecNamePlugIn.get(i));\r
962                                         rp.append("\t");\r
963                                 }\r
964                                 r.setDetail(dt.toString());\r
965                                 r.getHidden_params().put(RETVAL_KEY_R_RECFOLDER, rf.toString());\r
966                                 r.getHidden_params().put(RETVAL_KEY_R_WRITEPLUGIN, wp.toString());\r
967                                 r.getHidden_params().put(RETVAL_KEY_R_RECNAMEPLUGIN, rp.toString());\r
968                         }\r
969                         \r
970                         r.getHidden_params().put(RETVAL_KEY_PARTIALFOLDERCOUNT, String.valueOf(partialFolderCount));\r
971                         if ( partialFolderCount > 0 && pRecFolder.size() >= recFolderCount && pWritePlugIn.size() >= recFolderCount && pRecNamePlugIn.size() >= recFolderCount ) {\r
972                                 StringBuilder dt = new StringBuilder(r.getDetail());\r
973                                 StringBuilder rf = new StringBuilder();\r
974                                 StringBuilder wp = new StringBuilder();\r
975                                 StringBuilder rp = new StringBuilder();\r
976                                 for ( int i=0; i<recFolderCount; i++ ) {\r
977                                         dt.append("■[1SEG] 録画フォルダ・出力PlugIn・ファイル名PlugIn(");\r
978                                         dt.append(String.valueOf(i+1));\r
979                                         dt.append("):");\r
980                                         dt.append(pRecFolder.get(i));\r
981                                         dt.append(" / ");\r
982                                         dt.append(pWritePlugIn.get(i));\r
983                                         dt.append(" / ");\r
984                                         dt.append(pRecNamePlugIn.get(i));\r
985                                         dt.append("\n");\r
986                                         \r
987                                         rf.append(pRecFolder.get(i));\r
988                                         rf.append("\t");\r
989                                         \r
990                                         wp.append(pWritePlugIn.get(i));\r
991                                         wp.append("\t");\r
992                                         \r
993                                         rp.append(pRecNamePlugIn.get(i));\r
994                                         rp.append("\t");\r
995                                 }\r
996                                 r.setDetail(dt.toString());\r
997                                 r.getHidden_params().put(RETVAL_KEY_P_RECFOLDER, rf.toString());\r
998                                 r.getHidden_params().put(RETVAL_KEY_P_WRITEPLUGIN, wp.toString());\r
999                                 r.getHidden_params().put(RETVAL_KEY_P_RECNAMEPLUGIN, rp.toString());\r
1000                         }\r
1001                         \r
1002                         // 予定ファイル名\r
1003                         if ( recFileNameList.size() > 0 ) {\r
1004                                 StringBuilder dt = new StringBuilder(r.getDetail());\r
1005                                 for ( int i=0; i<recFileNameList.size(); i++ ) {\r
1006                                         dt.append("■予定ファイル名(");\r
1007                                         dt.append(String.valueOf(i+1));\r
1008                                         dt.append("):");\r
1009                                         dt.append(recFileNameList.get(i));\r
1010                                 }\r
1011                                 dt.append("\n");\r
1012                                 r.setDetail(dt.toString());\r
1013                         }\r
1014                         \r
1015                         // 番組ID\r
1016                         if ( evid != 0 && evid != 65535 ) {\r
1017                                 StringBuilder dt = new StringBuilder(r.getDetail());\r
1018                                 dt.append("■番組ID:");\r
1019                                 dt.append(contentid);\r
1020                                 dt.append("\n");\r
1021                                 r.setDetail(dt.toString());\r
1022                         }\r
1023                         \r
1024                         /*\r
1025                          *  既存予約一覧からの情報引き継ぎ\r
1026                          */\r
1027                         //XcopyAttributes(r, getReserves());\r
1028                         \r
1029                         /*\r
1030                          * 追加\r
1031                          */\r
1032                         newReserveList.add(r);\r
1033                 }\r
1034                 \r
1035                 return true;\r
1036         }\r
1037 \r
1038         /**\r
1039          * 予約詳細の取得【HTML版】(番組IDキー)\r
1040          */\r
1041         private boolean getRsvDetailByContentId(ReserveList r, int cnt) {\r
1042                 String pstr = genPoststrEPGA(r);\r
1043                 String url = "http://"+getIPAddr()+":"+getPortNo()+"/epginfo.html?"+pstr;\r
1044                 System.out.println("URL: "+url);\r
1045                 return getRsvDetail(r, url, cnt);\r
1046         }\r
1047         \r
1048         /**\r
1049          * 予約詳細の取得【HTML版】(予約IDキー)\r
1050          */\r
1051         private boolean getRsvDetailByReserveId(ReserveList r, int cnt) {\r
1052                 String url = "http://"+getIPAddr()+":"+getPortNo()+"/reserveinfo.html?id="+getRsvId(r.getId());\r
1053                 System.out.println("URL: "+url);\r
1054                 return getRsvDetail(r, url, cnt);\r
1055         }\r
1056         \r
1057         /**\r
1058          * 予約詳細の取得【HTML版】(共通)\r
1059          */\r
1060         private boolean getRsvDetail(ReserveList r, String url, int cnt) {\r
1061                 \r
1062                 reportProgress("+予約詳細を取得します("+cnt+")");\r
1063 \r
1064                 String[] d = reqGET(url,null);\r
1065                 if ( d[1] == null ) {\r
1066                         return false;\r
1067                 }\r
1068                 \r
1069                 return decodeRsvDetail(r, d[1], url);\r
1070         }\r
1071 \r
1072         /**\r
1073          * 予約詳細のデコード【HTML版】\r
1074          */\r
1075         private boolean decodeRsvDetail(ReserveList r, String res, String url) {\r
1076 \r
1077                 Matcher mb = null;\r
1078                 \r
1079                 try {\r
1080                         // 予約ID\r
1081                         mb = Pattern.compile("<form method=\"POST\" action=\"reservedel\\.html\\?id=(\\d+?)\">").matcher(res);\r
1082                         if ( mb.find() ) {\r
1083                                 r.setId(getUniqId(mb.group(1)));\r
1084                         }\r
1085                         \r
1086                         // イベントIDと予約方式\r
1087                         int evid = -1;\r
1088                         mb = Pattern.compile("EventID:\\d+\\(0x(.+)\\)").matcher(res);\r
1089                         if ( mb.find() ) {\r
1090                                 evid = Integer.decode("0X"+mb.group(1));\r
1091                                 setTextRecType(r,ITEM_REC_TYPE_EPG);\r
1092                         }\r
1093                         else {\r
1094                                 setTextRecType(r,ITEM_REC_TYPE_PROG);\r
1095                         }\r
1096 \r
1097                         // EPG予約場合のみの処理\r
1098                         if ( getTextRecType(r).equals(ITEM_REC_TYPE_EPG) ) {\r
1099                                 // 放送局\r
1100                                 int onid = -1;\r
1101                                 mb = Pattern.compile("OriginalNetworkID:\\d+\\(0x(.+)\\)").matcher(res);\r
1102                                 if ( mb.find() ) {\r
1103                                         onid = Integer.decode("0X"+mb.group(1));\r
1104                                 }\r
1105                                 int tsid = -1;\r
1106                                 mb = Pattern.compile("TransportStreamID:\\d+\\(0x(.+)\\)").matcher(res);\r
1107                                 if ( mb.find() ) {\r
1108                                         tsid = Integer.decode("0X"+mb.group(1));\r
1109                                 }\r
1110                                 int sid = -1;\r
1111                                 mb = Pattern.compile("ServiceID:\\d+\\(0x(.+)\\)").matcher(res);\r
1112                                 if ( mb.find() ) {\r
1113                                         sid = Integer.decode("0X"+mb.group(1));\r
1114                                 }\r
1115                                 if ( onid == -1 || tsid == -1 || sid == -1 ) {\r
1116                                         System.err.println("放送局IDが取得できませんでした: "+url);\r
1117                                 }\r
1118                                 else {\r
1119                                         String chid = String.valueOf(Long.decode("0x"+ContentIdEDCB.getChId(onid,tsid,sid)));\r
1120                                         r.setCh_name(cc.getCH_CODE2WEB(chid));\r
1121                                         r.setChannel(chid);\r
1122                                         \r
1123                                         r.setContentId(ContentIdEDCB.getContentId(onid,tsid,sid,evid));\r
1124                                 }\r
1125                                 \r
1126                                 // (1-X) 開始・終了日時と、番組詳細、タイトル\r
1127                                 // ★一覧の開始・終了日時は、登録した際の開始・終了日時のままなので詳細を参照して修正が必要\r
1128                                 mb = Pattern.compile("<HR>番組情報<HR>\\s*(\\d\\d\\d\\d/\\d\\d/\\d\\d\\(.\\)) (\\d\\d):(\\d\\d)~(\\d\\d):(\\d\\d)<BR>.+?<BR>\\s*(.*?)<BR>.*?<BR>\\s*(.+?)\\s*<HR>録画設定<HR>",Pattern.DOTALL).matcher(res);\r
1129                                 if ( mb.find() ) {\r
1130                                         GregorianCalendar cal = CommonUtils.getCalendar(mb.group(1));\r
1131                                         r.setRec_pattern(CommonUtils.getDate(cal));\r
1132                                         r.setRec_pattern_id(11);\r
1133                                         \r
1134                                         r.setStartDateTime(CommonUtils.getDateTime(cal));\r
1135                                         r.setRec_nextdate(r.getStartDateTime());\r
1136                                         r.setAhh(mb.group(2));\r
1137                                         r.setAmm(mb.group(3));\r
1138                                         r.setZhh(mb.group(4));\r
1139                                         r.setZmm(mb.group(5));\r
1140                                         \r
1141                                         r.setRec_nextdate(CommonUtils.getNextDate(r));\r
1142                                         r.setRec_min(CommonUtils.getRecMin(r.getAhh(), r.getAmm(), r.getZhh(), r.getZmm()));\r
1143                                         getStartEndDateTime(r);\r
1144                                         \r
1145                                         r.setTitle(CommonUtils.unEscape(mb.group(6)));\r
1146                                         r.setTitlePop(TraceProgram.replacePop(r.getTitle()));\r
1147                                         \r
1148                                         r.setDetail(CommonUtils.unEscape(mb.group(7)).replaceAll("<BR>", ""));\r
1149                                 }\r
1150                         }\r
1151                 }\r
1152                 catch ( Exception e ) {\r
1153                         e.printStackTrace();\r
1154                 }\r
1155                 \r
1156                 // (1-1)プリセット\r
1157                 setTextPresetID(r, getSelectedSetting("presetID",res));\r
1158                 \r
1159                 // (1-3)録画モード\r
1160                 {\r
1161                         String rec_mode = getSelectedSetting("recMode",res);\r
1162                         if ( rec_mode != null && rec_mode.equals(ITEM_REC_MODE_DISABLE) ) {\r
1163                                 // "無効"は「予約実行」で扱うので\r
1164                                 r.setExec(false);\r
1165                                 setTextRecMode(r,getListRecMode().get(0).getText());\r
1166                                 // チューナー不足警告(リスト取得時に立ててるので落とす)\r
1167                                 r.setTunershort(false);\r
1168                         }\r
1169                         else {\r
1170                                 setTextRecMode(r,rec_mode);\r
1171                         }\r
1172                 }\r
1173                 \r
1174                 // (1-4)エンコーダ\r
1175                 setTextTunerID(r, getSelectedSetting("tunerID",res));\r
1176                 \r
1177                 // (1-6)録画後動作\r
1178                 setTextSuspendMode(r, getSelectedSetting("suspendMode",res));\r
1179                 \r
1180                 // (1-10)追従\r
1181                 r.setPursues(ITEM_YES.equals(getSelectedSetting("tuijyuuFlag",res)));\r
1182                 \r
1183                 // (1-11)ぴったり\r
1184                 setTextPittariFlag(r, getSelectedSetting("pittariFlag",res));\r
1185                 \r
1186                 // (1-12)録画優先度\r
1187                 setTextPriority(r, getSelectedSetting("priority",res));\r
1188                 \r
1189                 // (1-13)連続録画動作\r
1190                 if ( getCheckedSetting("continueRecFlag", res) != null ) {\r
1191                         setTextContinueRecFlag(r, ITEM_YES);\r
1192                 }\r
1193                 else {\r
1194                         setTextContinueRecFlag(r, ITEM_NO);\r
1195                 }\r
1196                 \r
1197                 // (1-14)復帰後再起動\r
1198                 if ( getCheckedSetting("rebootFlag", res) != null ) {\r
1199                         setTextRebootFlag(r, ITEM_YES);\r
1200                 }\r
1201                 else {\r
1202                         setTextRebootFlag(r, ITEM_NO);\r
1203                 }\r
1204                 \r
1205                 // (1-15) 指定サービス対象データ\r
1206                 if ( getCheckedSetting("serviceMode", res) != null ) {\r
1207                         setTextServiceMode(r, ITEM_SERVMOCE_DEFAULT);\r
1208                 }\r
1209                 else {\r
1210                         boolean b1 = "0".equals(getCheckedSetting("serviceMode_1", res));\r
1211                         boolean b2 = "0".equals(getCheckedSetting("serviceMode_2", res));\r
1212                         if ( b1 && b2 ) {\r
1213                                 setTextServiceMode(r, ITEM_SERVMOCE_SUBTCARO);\r
1214                         }\r
1215                         else if ( b1 ) {\r
1216                                 setTextServiceMode(r, ITEM_SERVMOCE_SUBT);\r
1217                         }\r
1218                         else if ( b2 ) {\r
1219                                 setTextServiceMode(r, ITEM_SERVMOCE_CARO);\r
1220                         }\r
1221                         else {\r
1222                                 setTextServiceMode(r, ITEM_SERVMOCE_NONE);\r
1223                         }\r
1224                 }\r
1225                 \r
1226                 // (1-16) 録画マージン\r
1227                 {\r
1228                         if ( getCheckedSetting("useDefMargineFlag", res) != null ) {\r
1229                                 setTextStartMargine(r, ITEM_MARGINE_DEFAULT);\r
1230                                 setTextEndMargine(r, ITEM_MARGINE_DEFAULT);\r
1231                         }\r
1232                         else {\r
1233                                 setTextStartMargine(r, getEditedSetting("startMargine", res));\r
1234                                 setTextEndMargine(r, getEditedSetting("endMargine", res));\r
1235                         }\r
1236                 }\r
1237                 \r
1238                 // (1-17) 別ファイルに同時出力する\r
1239                 if ( getCheckedSetting("partialRecFlag", res) != null ) {\r
1240                         setTextPartialRecFlag(r, ITEM_YES);\r
1241                 }\r
1242                 else {\r
1243                         setTextPartialRecFlag(r, ITEM_NO);\r
1244                 }\r
1245                 \r
1246                 String batFilePath = null;\r
1247                 ArrayList<String> rRecFolder = new ArrayList<String>();\r
1248                 ArrayList<String> rWritePlugIn = new ArrayList<String>();\r
1249                 ArrayList<String> rRecNamePlugIn = new ArrayList<String>();\r
1250                 ArrayList<String> pRecFolder = new ArrayList<String>();\r
1251                 ArrayList<String> pWritePlugIn = new ArrayList<String>();\r
1252                 ArrayList<String> pRecNamePlugIn = new ArrayList<String>();\r
1253                 \r
1254                 // 録画後実行bat\r
1255                 mb = Pattern.compile("録画後実行bat.*?:\\s*(.*?)<BR>",Pattern.DOTALL).matcher(res);\r
1256                 if ( mb.find() ) {\r
1257                         batFilePath = mb.group(1);\r
1258                 }\r
1259                 \r
1260                 // オプショナル\r
1261                 {\r
1262                         // 録画フォルダ等\r
1263                         Matcher mc = Pattern.compile("録画フォルダ.*?(<TABLE.*?</TABLE>)\\s*<input type=hidden name=\"recFolderCount\" value=\"(\\d+?)\">",Pattern.DOTALL).matcher(res);\r
1264                         if ( ! mc.find() ) {\r
1265                                 errmsg = "情報が見つかりません:"+RETVAL_KEY_RECFOLDERCOUNT;\r
1266                         }\r
1267                         else {\r
1268                                 r.getHidden_params().put(RETVAL_KEY_RECFOLDERCOUNT, mc.group(2));\r
1269                                 \r
1270                                 Matcher md = Pattern.compile("<TR>(.*?)</TR>",Pattern.DOTALL).matcher(mc.group(1));\r
1271                                 int idx = 0;\r
1272                                 while ( md.find() ) {\r
1273                                         if ( idx++ == 0 ) {\r
1274                                                 continue;\r
1275                                         }\r
1276                                         Matcher me = Pattern.compile("<TD>(.*?)</TD>",Pattern.DOTALL).matcher(md.group(1));\r
1277                                         for ( int i=0; i<3 && me.find(); i++ ) {\r
1278                                                 switch (i) {\r
1279                                                 case 0:\r
1280                                                         rRecFolder.add(me.group(1));\r
1281                                                         break;\r
1282                                                 case 1:\r
1283                                                         rWritePlugIn.add(me.group(1));\r
1284                                                         break;\r
1285                                                 case 2:\r
1286                                                         rRecNamePlugIn.add(me.group(1));\r
1287                                                         break;\r
1288                                                 }\r
1289                                         }\r
1290                                 }\r
1291                         }\r
1292                         \r
1293                         // 録画フォルダ等(ワンセグ)\r
1294                         mc = Pattern.compile("partialRecFlag.*?(<TABLE.*?</TABLE>)\\s*<input type=hidden name=\"partialFolderCount\" value=\"(\\d+?)\">",Pattern.DOTALL).matcher(res);\r
1295                         if ( ! mc.find() ) {\r
1296                                 errmsg = "情報が見つかりません:"+RETVAL_KEY_PARTIALFOLDERCOUNT;\r
1297                         }\r
1298                         else {\r
1299                                 r.getHidden_params().put(RETVAL_KEY_PARTIALFOLDERCOUNT, mc.group(2));\r
1300                                 \r
1301                                 \r
1302                                 Matcher md = Pattern.compile("<TR>(.*?)</TR>",Pattern.DOTALL).matcher(mc.group(1));\r
1303                                 int idx = 0;\r
1304                                 while ( md.find() ) {\r
1305                                         if ( idx++ == 0 ) {\r
1306                                                 continue;\r
1307                                         }\r
1308                                         Matcher me = Pattern.compile("<TD>(.*?)</TD>",Pattern.DOTALL).matcher(md.group(1));\r
1309                                         for ( int i=0; i<3 && me.find(); i++ ) {\r
1310                                                 switch (i) {\r
1311                                                 case 0:\r
1312                                                         pRecFolder.add(me.group(1));\r
1313                                                         break;\r
1314                                                 case 1:\r
1315                                                         pWritePlugIn.add(me.group(1));\r
1316                                                         break;\r
1317                                                 case 2:\r
1318                                                         pRecNamePlugIn.add(me.group(1));\r
1319                                                         break;\r
1320                                                 }\r
1321                                         }\r
1322                                 }\r
1323                         }\r
1324                 }\r
1325                 \r
1326                 {\r
1327                         StringBuilder dt = new StringBuilder("■予約状況:");\r
1328                         if ( r.getContentId() != null ) {\r
1329                                 dt.append("EPG予約(自動手動不明→予約一覧再取得を行ってください)");\r
1330                         }\r
1331                         else {\r
1332                                 dt.append("プログラム予約");\r
1333                         }\r
1334                         dt.append("\n");\r
1335                         r.setDetail(dt.toString());\r
1336                 }\r
1337                 \r
1338                 if ( batFilePath != null && batFilePath.length() > 0 ) {\r
1339                         StringBuilder dt = new StringBuilder(r.getDetail());\r
1340                         dt.append("■録画後実行bat:");\r
1341                         dt.append(batFilePath);\r
1342                         dt.append("\n");\r
1343                         r.setDetail(dt.toString());\r
1344                 }\r
1345                 \r
1346                 if ( rRecFolder.size() > 0 ) {\r
1347                         StringBuilder dt = new StringBuilder(r.getDetail());\r
1348                         StringBuilder rf = new StringBuilder();\r
1349                         StringBuilder wp = new StringBuilder();\r
1350                         StringBuilder rp = new StringBuilder();\r
1351                         for ( int i=0; i<rRecFolder.size(); i++ ) {\r
1352                                 dt.append("■録画フォルダ・出力PlugIn・ファイル名PlugIn(");\r
1353                                 dt.append(String.valueOf(i+1));\r
1354                                 dt.append("):");\r
1355                                 dt.append(rRecFolder.get(i));\r
1356                                 dt.append(" / ");\r
1357                                 dt.append(rWritePlugIn.get(i));\r
1358                                 dt.append(" / ");\r
1359                                 dt.append(rRecNamePlugIn.get(i));\r
1360                                 dt.append("\n");\r
1361                                 \r
1362                                 rf.append(rRecFolder.get(i));\r
1363                                 rf.append("\t");\r
1364                                 \r
1365                                 wp.append(rWritePlugIn.get(i));\r
1366                                 wp.append("\t");\r
1367                                 \r
1368                                 rp.append(rRecNamePlugIn.get(i));\r
1369                                 rp.append("\t");\r
1370                         }\r
1371                         r.setDetail(dt.toString());\r
1372                         r.getHidden_params().put(RETVAL_KEY_R_RECFOLDER, rf.toString());\r
1373                         r.getHidden_params().put(RETVAL_KEY_R_WRITEPLUGIN, wp.toString());\r
1374                         r.getHidden_params().put(RETVAL_KEY_R_RECNAMEPLUGIN, rp.toString());\r
1375                 }\r
1376                 \r
1377                 if ( pRecFolder.size() > 0 ) {\r
1378                         StringBuilder dt = new StringBuilder(r.getDetail());\r
1379                         StringBuilder rf = new StringBuilder();\r
1380                         StringBuilder wp = new StringBuilder();\r
1381                         StringBuilder rp = new StringBuilder();\r
1382                         for ( int i=0; i<rRecFolder.size(); i++ ) {\r
1383                                 dt.append("■[1SEG] 録画フォルダ・出力PlugIn・ファイル名PlugIn(");\r
1384                                 dt.append(String.valueOf(i+1));\r
1385                                 dt.append("):");\r
1386                                 dt.append(pRecFolder.get(i));\r
1387                                 dt.append(" / ");\r
1388                                 dt.append(pWritePlugIn.get(i));\r
1389                                 dt.append(" / ");\r
1390                                 dt.append(pRecNamePlugIn.get(i));\r
1391                                 dt.append("\n");\r
1392                                 \r
1393                                 rf.append(pRecFolder.get(i));\r
1394                                 rf.append("\t");\r
1395                                 \r
1396                                 wp.append(pWritePlugIn.get(i));\r
1397                                 wp.append("\t");\r
1398                                 \r
1399                                 rp.append(pRecNamePlugIn.get(i));\r
1400                                 rp.append("\t");\r
1401                         }\r
1402                         r.setDetail(dt.toString());\r
1403                         r.getHidden_params().put(RETVAL_KEY_P_RECFOLDER, rf.toString());\r
1404                         r.getHidden_params().put(RETVAL_KEY_P_WRITEPLUGIN, wp.toString());\r
1405                         r.getHidden_params().put(RETVAL_KEY_P_RECNAMEPLUGIN, rp.toString());\r
1406                 }\r
1407                 \r
1408                 // 番組ID\r
1409                 if ( r.getContentId() != null && r.getContentId().length() > 0 ) {\r
1410                         StringBuilder dt = new StringBuilder(r.getDetail());\r
1411                         dt.append("■番組ID:");\r
1412                         dt.append(ContentIdEDCB.stripMark(r.getContentId()));\r
1413                         dt.append("\n");\r
1414                         r.setDetail(dt.toString());\r
1415                 }\r
1416 \r
1417                 return true;\r
1418         }\r
1419         private String getSelectedSetting(String key, String res) {\r
1420                 Matcher mb = Pattern.compile("<select name=\""+key+"\">[\\s\\S]*?<option value=\"([^\"]+?)\"\\s*selected>(.+?)\n").matcher(res);\r
1421                 if (mb.find()) {\r
1422                         return mb.group(2);\r
1423                 }\r
1424                 return null;\r
1425         }\r
1426         private String getEditedSetting(String key, String res) {\r
1427                 Matcher mb = Pattern.compile("<input type=text name=\""+key+"\" value=\"([^\"]+?)\">").matcher(res);\r
1428                 if (mb.find()) {\r
1429                         return mb.group(1);\r
1430                 }\r
1431                 return null;\r
1432         }\r
1433         private String getCheckedSetting(String key, String res) {\r
1434                 Matcher mb = Pattern.compile("<input type=checkbox name=\""+key+"\" value=\"([^\"]+?)\" checked>").matcher(res);\r
1435                 if (mb.find()) {\r
1436                         return mb.group(1);\r
1437                 }\r
1438                 return null;\r
1439         }\r
1440         \r
1441         \r
1442         /*------------------------------------------------------------------------------\r
1443          * 自動予約一覧の取得\r
1444          *------------------------------------------------------------------------------/\r
1445         \r
1446         /**\r
1447          * 自動予約一覧を取得する\r
1448          */\r
1449         private boolean getAutoReserveList(AutoReserveInfoList newAutoReserveList) {\r
1450                 if ( ! getAutorsvList(newAutoReserveList) ) {\r
1451                         // 一覧が取得できなかった\r
1452                         return false;\r
1453                 }\r
1454                 if ( ! getAutorsvDetailAll(newAutoReserveList) ) {\r
1455                         // 詳細が取得できなかった\r
1456                         return false;\r
1457                 }\r
1458                 return true;\r
1459         }\r
1460         \r
1461         /**\r
1462          * 自動予約一覧を取得する(リスト部)\r
1463          */\r
1464         private boolean getAutorsvList(AutoReserveInfoList newAutoReserveList) {\r
1465                 \r
1466                 int maxpage = 1;                        // 初期値は"1"!\r
1467                 String firstResp = null;        // 2回読み出したくない\r
1468 \r
1469                 String url = "http://"+getIPAddr()+":"+getPortNo()+"/autoaddepg.html&page=";\r
1470                 \r
1471                 {\r
1472                         reportProgress("自動予約一覧のページ数を取得します.");\r
1473                         String[] d = reqGET(url+"0",null);\r
1474                         if (d[1] == null) {\r
1475                                 errmsg = "レコーダーが反応しません";\r
1476                                 return false;\r
1477                         }\r
1478                         \r
1479                         firstResp = d[1];\r
1480                         \r
1481                         // maxpageの計算が入る\r
1482                         Matcher ma = Pattern.compile("\"autoaddepg\\.html\\?page=").matcher(firstResp);\r
1483                         while ( ma.find() ) {\r
1484                                 ++maxpage;\r
1485                         }\r
1486                 }\r
1487                 \r
1488                 for ( int i=0; i<maxpage; i++ ) {\r
1489                         \r
1490                         reportProgress(String.format("+自動予約一覧を取得します(%d/%d)",(i+1),maxpage));\r
1491                         \r
1492                         String response;\r
1493                         if ( i == 0 ) {\r
1494                                 response = firstResp;\r
1495                         }\r
1496                         else {\r
1497                                 // あとで\r
1498                                 String[] d = reqGET(url+String.valueOf(i+1),null);\r
1499                                 if (d[1] == null) {\r
1500                                         errmsg = "レコーダーが反応しません";\r
1501                                         return false;\r
1502                                 }\r
1503                                 \r
1504                                 response = d[1];\r
1505                         }\r
1506                         \r
1507                         Matcher ma = Pattern.compile("<TR>(.+?)</TR>",Pattern.DOTALL).matcher(response);\r
1508                         while ( ma.find() ) {\r
1509                                 // 入れ物用意\r
1510                                 AutoReserveInfo c = new AutoReserveInfo();\r
1511                                 \r
1512                                 // 分解\r
1513                                 Matcher mb = Pattern.compile("<TD>(.*?)</TD>",Pattern.DOTALL).matcher(ma.group(1));\r
1514                                 for ( int n=0; mb.find(); n++ ) {\r
1515                                         switch (n) {\r
1516                                         case 0: // title\r
1517                                                 c.setLabel(CommonUtils.unEscape(mb.group(1)));\r
1518                                                 break;\r
1519                                         case 5: // id\r
1520                                                 Matcher mc = Pattern.compile("\"autoaddepginfo\\.html\\?id=(.+)\"",Pattern.DOTALL).matcher(mb.group(1));\r
1521                                                 if ( mc.find() ) {\r
1522                                                         c.setId(mc.group(1));\r
1523                                                 }\r
1524                                                 break;\r
1525                                         case 3: // channel\r
1526                                                 //c.getChannels().add(CommonUtils.unEscape(mb.group(1)));\r
1527                                                 break;\r
1528                                         case 1: // mark\r
1529                                         case 2: // genre\r
1530                                         case 4: // service\r
1531                                         default:\r
1532                                                 break;\r
1533                                         }\r
1534                                 }\r
1535                                 if ( c.getId() == null ) {\r
1536                                         c = null;\r
1537                                         continue;       // 情報がみつからなかった\r
1538                                 }\r
1539                                 \r
1540                                 newAutoReserveList.add(c);\r
1541                         }\r
1542                 }\r
1543                 \r
1544                 return true;\r
1545         }\r
1546         \r
1547         /**\r
1548          * 自動予約一覧を取得する(詳細部)\r
1549          */\r
1550         private boolean getAutorsvDetailAll(AutoReserveInfoList newAutoReserveList) {\r
1551                 \r
1552                 String url = "http://"+getIPAddr()+":"+getPortNo()+"/autoaddepginfo.html?id=";\r
1553                 \r
1554                 int cnt = 0;\r
1555                 for ( AutoReserveInfo c : newAutoReserveList ) {\r
1556 \r
1557                         ++cnt;\r
1558                         \r
1559                         reportProgress(String.format("自動予約詳細を取得します(%d/%d)",cnt,newAutoReserveList.size()));\r
1560                         String[] d = reqGET(url+c.getId(),null);\r
1561                         if (d[1] == null) {\r
1562                                 errmsg = "レコーダーが反応しません";\r
1563                                 return false;\r
1564                         }\r
1565                         \r
1566                         if ( ! decodeAutorsvDetail(c, d[1]) ) {\r
1567                                 // デコードできなかった\r
1568                                 System.err.println("★★★ スクリプト解析まで仮置き ★★★ ");\r
1569                                 CommonUtils.printStackTrace();\r
1570                         }\r
1571                 }\r
1572                 \r
1573                 return true;\r
1574         }\r
1575         \r
1576         /**\r
1577          * 自動予約詳細をデコードする\r
1578          */\r
1579         private boolean decodeAutorsvDetail(AutoReserveInfo c, String str) {\r
1580                 \r
1581                 String[] data = str.split("<HR>録画設定<HR>");\r
1582                 if ( data.length != 2 ) {\r
1583                         return false;\r
1584                 }\r
1585 \r
1586                 // キーワード設定部\r
1587                 {\r
1588                         // テキストボックスの場合\r
1589                         {\r
1590                                 Matcher mb = Pattern.compile("<input type=\"text\" name=\"(.+?)\" value=\"(.*?)\" size=", Pattern.DOTALL).matcher(data[0]);\r
1591                                 while ( mb.find() ) {\r
1592                                         if ( mb.group(1).equals("andKey") ) {\r
1593                                                 c.setLabel(CommonUtils.unEscape(mb.group(2)));\r
1594                                                 c.setKeyword(c.getLabel());\r
1595                                         }\r
1596                                         else if ( mb.group(1).equals("notKey") ) {\r
1597                                                 c.setExKeyword(CommonUtils.unEscape(mb.group(2)));\r
1598                                         }\r
1599                                         else if ( mb.group(1).equals("dateList") ) {\r
1600                                                 \r
1601                                         }\r
1602                                         else if ( mb.group(1).equals("chkRecDay") ) {\r
1603                                                 try {\r
1604                                                         c.setRecordedCheckTerm(Integer.valueOf(mb.group(2)));\r
1605                                                         continue;\r
1606                                                 }\r
1607                                                 catch ( NumberFormatException e) {\r
1608                                                         e.printStackTrace();\r
1609                                                 }\r
1610                                                 c.setRecordedCheckTerm(6);              // デフォルトバリュー\r
1611                                         }\r
1612                                 }\r
1613                         }\r
1614                         \r
1615                         // コンボボックスの場合\r
1616                         {\r
1617                                 Matcher mb = Pattern.compile("<select name=\"(.+?)\" .*?size=\\d+?>(.*?)</select>", Pattern.DOTALL).matcher(data[0]);\r
1618                                 while ( mb.find() ) {\r
1619                                         if ( mb.group(1).equals("contentList") ) {\r
1620                                                 // ジャンル\r
1621                                         }\r
1622                                         else if ( mb.group(1).equals("serviceList") ) {\r
1623                                                 \r
1624                                                 // 放送局\r
1625                                                 Matcher mc = Pattern.compile("<option value=\"(\\d+?)\" selected>", Pattern.DOTALL).matcher(mb.group(2));\r
1626                                                 while ( mc.find() ) {\r
1627                                                         String chName = cc.getCH_CODE2WEB(mc.group(1));\r
1628                                                         c.getChannels().add((chName!=null) ? chName : mc.group(1));\r
1629                                                 }\r
1630                                         }\r
1631                                         \r
1632                                 }\r
1633                         }\r
1634                 }\r
1635                 \r
1636                 // 録画設定部\r
1637                 {\r
1638                         ReserveInfo r = new ReserveInfo();\r
1639                         decodeRsvDetail(r, data[1], null);\r
1640                         c.setRecSetting(r);\r
1641                 }\r
1642                 \r
1643                 return true;\r
1644         }\r
1645         \r
1646         \r
1647         /*------------------------------------------------------------------------------\r
1648          * 録画結果一覧の取得\r
1649          *------------------------------------------------------------------------------/\r
1650          *\r
1651         /**\r
1652          *      録画結果一覧を取得する\r
1653          */\r
1654         private boolean getRecedList(ArrayList<RecordedInfo> newRecordedList) {\r
1655                 \r
1656                 String critDate = null;\r
1657                 if ( newRecordedList.size() > 0 ) {\r
1658                         // 最新の情報の前日分までチェックする\r
1659                         GregorianCalendar cal = CommonUtils.getCalendar(newRecordedList.get(0).getDate());\r
1660                         cal.add(Calendar.DATE, -1);\r
1661                         critDate = CommonUtils.getDate(cal);\r
1662                 }\r
1663                 else {\r
1664                         // 既存情報が無ければ上限まで\r
1665                         critDate = CommonUtils.getDate(CommonUtils.getCalendar(-86400*getRecordedSaveScope()));\r
1666                 }\r
1667                 \r
1668                 if (getDebug()) System.out.println(DBGID+"録画結果の取り込みはここまで: "+critDate);\r
1669                 \r
1670                 // RDから予約一覧を取り出す\r
1671                 String response="";\r
1672                 {\r
1673                         reportProgress("録画結果一覧を取得します.(1)");\r
1674                         String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/recinfo.html",null);\r
1675                         response = d[1];\r
1676                         \r
1677                         if (response == null) {\r
1678                                 errmsg = "レコーダーが反応しません";\r
1679                                 return false;\r
1680                         }\r
1681                 }\r
1682 \r
1683                 // 30件を超えるとページが増える\r
1684                 int maxpage = 0;\r
1685                 Matcher ma = Pattern.compile("\"recinfo.html\\?page=(\\d+)\"").matcher(response);\r
1686                 while ( ma.find() ) {\r
1687                         int page = Integer.valueOf(ma.group(1));\r
1688                         if ( maxpage < page ) {\r
1689                                 maxpage = page;\r
1690                         }\r
1691                 }\r
1692                 \r
1693                 for ( int page = 0; page<=maxpage; page++ ) {\r
1694                         if ( page > 0 ) {\r
1695                                 reportProgress(String.format("録画結果一覧を取得します.(%d)",page+1));\r
1696                                 String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/recinfo.html?page="+page,null,thisEncoding);\r
1697                                 response = d[1];\r
1698                         }\r
1699                         if ( decodeRecedList(newRecordedList, response, critDate) <= 0) {\r
1700                                 // おわったぽ\r
1701                                 break;\r
1702                         }\r
1703                 }\r
1704 \r
1705                 return true;\r
1706         }\r
1707         \r
1708         /**\r
1709          * 録画一覧のデコード\r
1710          */\r
1711         private int decodeRecedList(ArrayList<RecordedInfo> newRecordedList, String response, String critDate) {\r
1712                 \r
1713                 int cnt = 0;\r
1714                 \r
1715                 //\r
1716                 Matcher mc = Pattern.compile("<TABLE BORDER=\"1\">(.+?)</TABLE>",Pattern.DOTALL).matcher(response);\r
1717                 if (mc.find()) {\r
1718                         Matcher ma = Pattern.compile("<TR( BGCOLOR=#......)?><TD>(\\d\\d\\d\\d/\\d\\d/\\d\\d)\\(.\\) (\\d\\d):(\\d\\d)~(\\d\\d):(\\d\\d)</TD><TD>(.+?)</TD>.*?<A HREF=\"recinfodesc\\.html\\?id=(\\d+?)\">詳細</A></TD></TR>\\s*?<TR( BGCOLOR=#......)?><TD COLSPAN=\"2\">(.*?)</TD></TR>\\s*?<TR( BGCOLOR=#......)?><TD COLSPAN=\"2\">(.*?)</TD></TR>",Pattern.DOTALL).matcher(mc.group(1));\r
1719                         while ( ma.find() ) {\r
1720                                 \r
1721                                 // 日付を調べる\r
1722                                 GregorianCalendar cal = CommonUtils.getCalendar(ma.group(2));\r
1723                                 String date = CommonUtils.getDate(cal);\r
1724                                 \r
1725                                 // 既存の情報に追いついたので取得終了\r
1726                                 if ( date.compareTo(critDate) < 0 ) {\r
1727                                         return -1;\r
1728                                 }\r
1729                                 \r
1730                                 // 個々のデータを取り出す\r
1731                                 RecordedInfo entry = new RecordedInfo();\r
1732 \r
1733                                 entry.setDate(date);\r
1734                                 \r
1735                                 entry.setAhh(ma.group(3));\r
1736                                 entry.setAmm(ma.group(4));\r
1737                                 entry.setZhh(ma.group(5));\r
1738                                 entry.setZmm(ma.group(6));\r
1739                                 \r
1740                                 long lenL = CommonUtils.getCompareDateTime(entry.getDate()+" "+entry.getZhh()+":"+entry.getZmm(), entry.getDate()+" "+entry.getAhh()+":"+entry.getAmm());\r
1741                                 if ( lenL < 0 ) {\r
1742                                         lenL += 86400000;\r
1743                                 }\r
1744                                 int len =  (int) (lenL / 60000L);\r
1745                                 entry.setLength(len);\r
1746                                 \r
1747                                 // 放送局(仮)\r
1748                                 String recChName = ma.group(7);\r
1749                                 String chid = cc.getCH_REC2CODE(recChName);\r
1750                                 if ( chid == null ) {\r
1751                                         // 難視聴対策局対策\r
1752                                         String nan = TEXT_NANSHICHO_HEADER+recChName;\r
1753                                         chid = cc.getCH_REC2CODE(nan);\r
1754                                         if ( chid != null ) {\r
1755                                                 recChName = nan;\r
1756                                         }\r
1757                                 }\r
1758                                 \r
1759                                 if ( chid == null ) {\r
1760                                         // CHコードにできなければ、HTMLから取得した放送局名をそのまま使う\r
1761                                         entry.setChannel(null);\r
1762                                         entry.setCh_name(recChName);\r
1763                                 }\r
1764                                 else {\r
1765                                         entry.setChannel(chid);\r
1766                                         String ch_name = cc.getCH_CODE2WEB(chid);\r
1767                                         if ( ch_name == null ) {\r
1768                                                 // CHコード設定がうまくないようですよ?\r
1769                                                 entry.setCh_name(ma.group(7));\r
1770                                         }\r
1771                                         else {\r
1772                                                 entry.setCh_name(ch_name);\r
1773                                         }\r
1774                                 }\r
1775                                 \r
1776                                 entry.setCh_orig(recChName);\r
1777                                 \r
1778                                 // ID\r
1779                                 entry.setId(ma.group(8));\r
1780                                 \r
1781                                 // 予約名\r
1782                                 entry.setTitle(CommonUtils.unEscape(ma.group(10)).replaceAll("<BR>", ""));\r
1783                                 \r
1784                                 // 録画結果\r
1785                                 entry.setResult(ma.group(12));\r
1786                                 entry.setSucceeded(entry.getResult().matches("^(録画終了|開始時間が変更されました)$"));\r
1787                                 \r
1788                                 // その他\r
1789                                 \r
1790                                 addRecorded(newRecordedList, entry);\r
1791                                 \r
1792                                 ++cnt;\r
1793                         }\r
1794                 }\r
1795                 \r
1796                 return cnt;\r
1797         }\r
1798 \r
1799         /**\r
1800          * 録画詳細の取得\r
1801          */\r
1802         private boolean getRecedDetailAll(ArrayList<RecordedInfo> newRecordedList) {\r
1803                 // 詳細情報を取得する\r
1804                 int i=0;\r
1805                 for ( RecordedInfo entry : newRecordedList ) {\r
1806                         \r
1807                         if ( entry.getId() == null ) {\r
1808                                 // 過去ログかな…?\r
1809                                 continue;\r
1810                         }\r
1811                         \r
1812                         ++i;\r
1813                         \r
1814                         reportProgress("+録画結果詳細を取得します("+i+")");\r
1815                         \r
1816                         String response="";\r
1817                         {\r
1818                                 String[] d = reqGET("http://"+getIPAddr()+":"+getPortNo()+"/recinfodesc.html?id="+entry.getId(),null);\r
1819                                 response = d[1];\r
1820                                 \r
1821                                 if (response == null) {\r
1822                                         errmsg = "レコーダーが反応しません";\r
1823                                         return false;\r
1824                                 }\r
1825                         }\r
1826                         \r
1827                         Matcher ma = Pattern.compile("ドロップ:(\\d+)", Pattern.DOTALL).matcher(response);\r
1828                         if ( ma.find() ) {\r
1829                                 entry.setDrop(Integer.valueOf(ma.group(1)));\r
1830                         }\r
1831                         \r
1832                         ma = Pattern.compile("Drop:\\s*(\\d+)\\s*Scramble:\\s*(\\d+)\\s*MPEG2", Pattern.DOTALL).matcher(response);\r
1833                         while ( ma.find() ) {\r
1834                                 entry.setDrop_mpeg(entry.getDrop_mpeg()+Integer.valueOf(ma.group(1)));\r
1835                         }\r
1836                         \r
1837                         ma = Pattern.compile("(<HR>番組情報<HR>.*</PRE>)", Pattern.DOTALL).matcher(response);\r
1838                         if ( ma.find() ) {\r
1839                                 entry.setDetail(CommonUtils.unEscape(ma.group(1).replaceAll("<BR>", "").replaceAll("</?PRE>", "").replaceAll("<HR>", "====").replaceAll("\n\n+", "\n\n")/*.replaceFirst("^([\\s\\S]*?)(====エラーログ====[\\s\\S]*?)$","$2\n\n$1")*/));\r
1840                         }\r
1841                         \r
1842                         // 放送局(訂正)\r
1843                         Matcher md = Pattern.compile("OriginalNetworkID:(\\d+).*?TransportStreamID:(\\d+).*?ServiceID:(\\d+)",Pattern.DOTALL).matcher(response);\r
1844                         if ( md.find() ) {\r
1845                                 // 詳細情報からCHコードが取得できるなら\r
1846                                 String chid = String.valueOf(Long.decode("0x"+ContentIdEDCB.getChId(Integer.valueOf(md.group(1)),Integer.valueOf(md.group(2)),Integer.valueOf(md.group(3)))));\r
1847                                 entry.setChannel(chid);\r
1848                                 String ch_name = cc.getCH_CODE2WEB(chid);\r
1849                                 if ( ch_name != null ) {\r
1850                                         entry.setCh_name(ch_name);\r
1851                                 }\r
1852                         }\r
1853                         \r
1854 \r
1855                 }\r
1856                 return true;\r
1857         }\r
1858 \r
1859         \r
1860         /*******************************************************************************\r
1861          * 新規予約\r
1862          ******************************************************************************/\r
1863         \r
1864         @Override\r
1865         public boolean PostRdEntry(ReserveList reqr)\r
1866         {\r
1867                 \r
1868                 ArrayList<ReserveList> tmprl = getReserves();\r
1869                 \r
1870                 boolean b = _PostRdEntry(reqr);\r
1871                 \r
1872                 // 予約一覧が更新されていたら、本体から取得できない情報は引き継ぐ\r
1873                 if ( getReserves() != tmprl ) {\r
1874                         copyAttributesAllList(tmprl, getReserves());\r
1875                 }\r
1876                 \r
1877                 // 成功しても失敗してもキャッシュが更新されている可能性があるので保存し直す\r
1878                 ReservesToFile(getReserves(), rsvedFile);\r
1879                 setRecordedFlag();\r
1880                 \r
1881                 return b;\r
1882         }\r
1883         private boolean _PostRdEntry(ReserveList reqr) \r
1884         {\r
1885                 //\r
1886                 System.out.println("Run: PostRdEntry("+reqr.getTitle()+")");\r
1887                 \r
1888                 errmsg = "";\r
1889 \r
1890                 // 放送局と日付のチェック\r
1891                 if ( ! PrePostCheck(reqr) ) {\r
1892                         return(false);\r
1893                 }\r
1894                 \r
1895                 // プリセット\r
1896                 if ( reqr.getRec_audio().equals(ITEM_PRESETID_REG) ) {\r
1897                         errmsg = "新規予約では次の指定はできません:プリセット="+ITEM_PRESETID_REG;\r
1898                         return false;\r
1899                 }\r
1900                 \r
1901                 // おまじない\r
1902                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
1903                 \r
1904                 String header;\r
1905                 String response;\r
1906                 \r
1907                 int onid = -1;\r
1908                 int tsid = -1;\r
1909                 int sid = -1;\r
1910                 int evid = -1;\r
1911                 \r
1912                 boolean rec_type_epg = true;\r
1913                 if ( getTextRecType(reqr) != null && getTextRecType(reqr).equals(ITEM_REC_TYPE_EPG) ) {\r
1914                         if ( ContentIdEDCB.isValid(reqr.getContentId()) ) {\r
1915                                 ContentIdEDCB.decodeContentId(reqr.getContentId());\r
1916                                 onid = ContentIdEDCB.getOnId();\r
1917                                 tsid = ContentIdEDCB.getTSId();\r
1918                                 sid = ContentIdEDCB.getSId();\r
1919                                 evid = ContentIdEDCB.getEvId();\r
1920                         }\r
1921                         else if ( ContentIdDIMORA.isValid(reqr.getContentId()) ) {\r
1922                                 ContentIdDIMORA.decodeContentId(reqr.getContentId());\r
1923                                 evid = ContentIdDIMORA.getEvId();\r
1924                                 // 後続処理あり\r
1925                         }\r
1926                         else if ( ContentIdREGZA.isValid(reqr.getContentId()) ) {\r
1927                                 ContentIdREGZA.decodeContentId(reqr.getContentId());\r
1928                                 evid = ContentIdREGZA.getEvId();\r
1929                                 // 後続処理あり\r
1930                         }\r
1931                         else {\r
1932                                 errmsg = "番組表に予約IDがないためEPG予約は利用できません。EDCB番組表を利用するかプログラム予約を行ってください。";\r
1933                                 return false;\r
1934                         }\r
1935                         \r
1936                         if ( evid != -1 && onid == -1 ) {\r
1937                                 // Dimora、REGZA形式の場合 onid と tsid が取得できないので自前の情報で補完\r
1938                                 ContentIdEDCB.decodeChId(ContentIdEDCB.getChId(cc.getCH_WEB2CODE(reqr.getCh_name())));\r
1939                                 onid = ContentIdEDCB.getOnId();\r
1940                                 tsid = ContentIdEDCB.getTSId();\r
1941                                 sid = ContentIdEDCB.getSId();\r
1942                                 // EDCB形式で置き換え\r
1943                                 reqr.setContentId(ContentIdEDCB.getContentId(onid, tsid, sid, evid));\r
1944                         }\r
1945                 }\r
1946                 else {\r
1947                         rec_type_epg = false;\r
1948                 }\r
1949                 \r
1950                 ReserveList newr = null;\r
1951                 \r
1952                 // 予約IDが含まれていたら削る\r
1953                 reqr.setId("");\r
1954                 \r
1955                 /*\r
1956                  *  EPG予約\r
1957                  */\r
1958                 if ( rec_type_epg ) {\r
1959                         \r
1960                         int cntMax = 3;\r
1961                         int cnt = 1;\r
1962                         \r
1963                         \r
1964                         // 番組情報ページを開く\r
1965                         {\r
1966                                 reportProgress(String.format("EPG予約を実行します(%d/%d).",cnt++,cntMax));\r
1967                                 \r
1968                                 ReserveList tmpr = new ReserveList();\r
1969                                 tmpr.setContentId(reqr.getContentId());\r
1970                                 setTextPresetID(tmpr, getTextPresetID(reqr));\r
1971                                 if ( ! getRsvDetailByContentId(tmpr,0) ) {\r
1972                                         errmsg = "予約ページが開けません。";\r
1973                                         return(false);\r
1974                                 }\r
1975                                 \r
1976                                 if ( tmpr.getId() != null && tmpr.getId().length() > 0 ) {\r
1977                                         System.out.println("重複予約が実行されます.");\r
1978                                 }\r
1979                         }\r
1980                         \r
1981                         // 予約登録を実行する\r
1982                         {               \r
1983                                 reportProgress(String.format("追加を実行します(%d/%d).",cnt++,cntMax));\r
1984                                 \r
1985                                 String pstr = genPoststrEPGB(reqr);\r
1986                                 String uri = "http://"+getIPAddr()+":"+getPortNo()+"/"+String.format("reserveadd.html?onid=%d&tsid=%d&sid=%d&evid=%d",onid,tsid,sid,evid);;\r
1987                                 \r
1988                                 System.err.println("URL: "+uri);\r
1989                                 \r
1990                                 header = response = null;\r
1991                                 for (int i=0; i<retryMax; i++) {\r
1992                                         String[] d = reqPOST(uri, pstr, null);\r
1993                                         header = d[0];\r
1994                                         response = d[1];\r
1995                                         if ( header != null && response == null ) {\r
1996                                                 reportProgress("コネクションがリセットされました。リトライします。");\r
1997                                                 CommonUtils.milSleep(1000);\r
1998                                         }\r
1999                                         else {\r
2000                                                 break;\r
2001                                         }\r
2002                                 }\r
2003                                 if ( header == null || response == null ) {\r
2004                                         errmsg = "レコーダーが反応しません。";\r
2005                                         return(false);\r
2006                                 }\r
2007                         }\r
2008                         \r
2009                         // EPG予約の場合はすぐわかる(はずだった→重複予約だとわからない)\r
2010                         {\r
2011                                 reportProgress(String.format("新しい予約IDを取得します(%d/%d).",cnt++,cntMax));\r
2012                                 \r
2013                                 newr = getRsvOnEdcbTR(reqr);\r
2014                                 if ( newr == null ) {\r
2015                                         return(false);\r
2016                                 }\r
2017                                 \r
2018                                 // 本体から取得できない情報は引き継ぐ\r
2019                                 copyAttributesMethod(reqr, newr);\r
2020                                 \r
2021                                 // 一発ヒットしたものはキャッシュ上にないので載せる\r
2022                                 if ( ! getReserves().contains(newr) ) {\r
2023                                         getReserves().add(newr);\r
2024                                 }\r
2025                                 \r
2026                                 reportProgress("+新しい予約ID: "+newr.getId());\r
2027                                 \r
2028                                 if ( isModified(reqr, newr) ) {\r
2029                                         errmsg = "EDCB番組表からの情報で内容が変更されました: "+newr.getStartDateTime()+"~"+newr.getZhh()+":"+newr.getZmm()+" "+newr.getTitle();\r
2030                                 }\r
2031                         }\r
2032                 }\r
2033                 \r
2034                 /*\r
2035                  * プログラム予約 \r
2036                  */\r
2037                 else {\r
2038                         \r
2039                         int cntMax = 3;\r
2040                         int cnt = 1;\r
2041                         \r
2042                         // プログラム予約の制限のチェック\r
2043                         if ( ! PreProgResCheck(reqr) ) {\r
2044                                 return(false);\r
2045                         }\r
2046                         \r
2047                         // 番組IDが含まれていたら削る\r
2048                         reqr.setContentId(null);\r
2049                         \r
2050                         // 予約情報の一部を確定する\r
2051                         {               \r
2052                                 reportProgress(String.format("プログラム予約を実行します(%d/%d).",cnt++,cntMax));\r
2053                                 \r
2054                                 String pstr = genPoststrDTA(reqr);\r
2055                                 String uri = "http://"+getIPAddr()+":"+getPortNo()+"/addprogres.html";\r
2056                                 \r
2057                                 System.err.println("URL: "+uri+"?"+pstr);\r
2058                                 \r
2059                                 header = response = null;\r
2060                                 for (int i=0; i<retryMax; i++) {\r
2061                                         String[] d = reqPOST(uri, pstr, null);\r
2062                                         header = d[0];\r
2063                                         response = d[1];\r
2064                                         if ( header != null && response == null ) {\r
2065                                                 reportProgress("コネクションがリセットされました。リトライします。");\r
2066                                                 CommonUtils.milSleep(1000);\r
2067                                         }\r
2068                                         else {\r
2069                                                 break;\r
2070                                         }\r
2071                                 }\r
2072                                 if ( header == null || response == null ) {\r
2073                                         errmsg = "レコーダーが反応しません。";\r
2074                                         return(false);\r
2075                                 }\r
2076 \r
2077                                 Matcher ma = Pattern.compile("<form method=\"POST\" action=\"reservepgadd.html\">").matcher(response);\r
2078                                 if ( ! ma.find() ) {\r
2079                                         errmsg = "予約に失敗しました。";\r
2080                                         return(false);\r
2081                                 }\r
2082                                 \r
2083                                 ma = Pattern.compile("<input type=hidden name=\"recFolderCount\" value=\"(\\d+?)\">").matcher(response);\r
2084                                 if ( ! ma.find() ) {\r
2085                                         errmsg = "予約に失敗しました。";\r
2086                                         return(false);\r
2087                                 }\r
2088                                 reqr.getHidden_params().put(RETVAL_KEY_RECFOLDERCOUNT, ma.group(1));\r
2089                                 \r
2090                                 ma = Pattern.compile("<input type=hidden name=\"partialFolderCount\" value=\"(\\d+?)\">").matcher(response);\r
2091                                 if ( ! ma.find() ) {\r
2092                                         errmsg = "予約に失敗しました。";\r
2093                                         return(false);\r
2094                                 }\r
2095                                 reqr.getHidden_params().put(RETVAL_KEY_PARTIALFOLDERCOUNT, ma.group(1));\r
2096                         }\r
2097                         \r
2098                         // 予約登録を実行する\r
2099                         {               \r
2100                                 reportProgress(String.format("追加を実行します(%d/%d).",cnt++,cntMax));\r
2101                                 \r
2102                                 String pstr = genPoststrDTB(reqr);\r
2103                                 String uri = "http://"+getIPAddr()+":"+getPortNo()+"/reservepgadd.html";\r
2104                                 \r
2105                                 System.err.println("URL: "+uri+"?"+pstr);\r
2106                                 \r
2107                                 header = response = null;\r
2108                                 for (int i=0; i<retryMax; i++) {\r
2109                                         String[] d = reqPOST(uri, pstr, null);\r
2110                                         header = d[0];\r
2111                                         response = d[1];\r
2112                                         if ( header != null && response == null ) {\r
2113                                                 reportProgress("コネクションがリセットされました。リトライします。");\r
2114                                                 CommonUtils.milSleep(1000);\r
2115                                         }\r
2116                                         else {\r
2117                                                 break;\r
2118                                         }\r
2119                                 }\r
2120                                 if ( header == null || response == null ) {\r
2121                                         errmsg = "レコーダーが反応しません。";\r
2122                                         return(false);\r
2123                                 }\r
2124                         }\r
2125                         \r
2126                         // EDCBに追加された予約IDを検索する ★EDCBは再起動すると予約IDが振り直しになるので必要!!\r
2127                         {\r
2128                                 reportProgress(String.format("新しい予約IDを番号を取得します(%d/%d).",cnt++,cntMax));\r
2129                                 \r
2130                                 reqr.setId(""); // 予約番号未定のためダミー\r
2131                                 newr = getRsvOnEdcbDT(reqr);\r
2132                                 if ( newr == null ) {\r
2133                                         errmsg = "予約IDがみつかりません。";\r
2134                                         return(false);\r
2135                                 }\r
2136                                 \r
2137                                 // 本体から取得できない情報は引き継ぐ\r
2138                                 copyAttributesMethod(reqr, newr);\r
2139 \r
2140                                 // 一発ヒットしたものはキャッシュ上にないので載せる\r
2141                                 if ( ! getReserves().contains(newr) ) {\r
2142                                         getReserves().add(newr);\r
2143                                 }\r
2144                                 \r
2145                                 reportProgress("+新しい予約ID: "+newr.getId());\r
2146                         }\r
2147                 }\r
2148                 \r
2149                 System.out.printf("\n<<< Message from RD >>> \"%s\"\n\n", "正常に登録できました。");\r
2150                 \r
2151                 return(true);\r
2152                 \r
2153                 // 長いよ!分割しる!!\r
2154         }\r
2155 \r
2156         \r
2157         /*******************************************************************************\r
2158          * 予約更新\r
2159          ******************************************************************************/\r
2160         \r
2161         /**\r
2162          * 予約を更新する(入口)\r
2163          */\r
2164         @Override\r
2165         public boolean UpdateRdEntry(ReserveList cacher, ReserveList reqr)\r
2166         {\r
2167                 ArrayList<ReserveList> tmprl = getReserves();\r
2168                 \r
2169                 boolean b = _UpdateRdEntry(cacher, reqr);\r
2170                 \r
2171                 // 予約一覧が更新されていたら、本体から取得できない情報は引き継ぐ\r
2172                 if ( getReserves() != tmprl ) {\r
2173                         copyAttributesAllList(tmprl, getReserves());\r
2174                 }\r
2175                 \r
2176                 // 成功しても失敗してもキャッシュが更新されている可能性があるので保存し直す\r
2177                 ReservesToFile(getReserves(), rsvedFile);\r
2178                 setRecordedFlag();\r
2179                 \r
2180                 return b;\r
2181         }\r
2182         \r
2183         /**\r
2184          * 予約を更新する(本体)\r
2185          */\r
2186         private boolean _UpdateRdEntry(ReserveList cacher, ReserveList reqr)\r
2187         {\r
2188                 //\r
2189                 System.out.println("Run: UpdateRdEntry()");\r
2190                 \r
2191                 errmsg = "";\r
2192                 \r
2193                 // おまじない\r
2194                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
2195                 \r
2196                 // 放送局と日付のチェック\r
2197                 if ( ! PrePostCheck(reqr) ) {\r
2198                         return(false);\r
2199                 }\r
2200                 \r
2201                 if ( ! getTextRecType(cacher).equals(getTextRecType(reqr)) ) {\r
2202                         errmsg = String.format("異なる予約方式への更新は行えません(%s->%s)",getTextRecType(cacher),getTextRecType(reqr));\r
2203                         return false;\r
2204                 }\r
2205                 \r
2206                 boolean rec_type_epg = true;\r
2207                 if ( getTextRecType(reqr) != null && getTextRecType(reqr).equals(ITEM_REC_TYPE_EPG) ) {\r
2208                         if ( ContentIdEDCB.isValid(reqr.getContentId()) ) {\r
2209                                 // 正しい番組IDのようですね\r
2210                         }\r
2211                         else {\r
2212                                 errmsg = "番組表に予約IDがないためEPG予約は利用できません。EDCB番組表を利用するかプログラム予約を行ってください。";\r
2213                                 return false;\r
2214                         }\r
2215                 }\r
2216                 else {\r
2217                         rec_type_epg = false;\r
2218                         // 番組IDが含まれていたら削る\r
2219                         reqr.setContentId(null);\r
2220                 }\r
2221                 \r
2222                 if ( rec_type_epg ) {\r
2223                         // EPG予約は普通に更新\r
2224                         if (getDebug()) System.err.println("[DEBUG] Update EPG RSV");\r
2225                         return UpdateRdEntryTR(cacher,reqr);\r
2226                 }\r
2227                 else {\r
2228                         \r
2229                         // プログラム予約の制限のチェック\r
2230                         if ( ! PreProgResCheck(reqr)) {\r
2231                                 return(false);\r
2232                         }\r
2233                         \r
2234                         // プログラム予約\r
2235                         if ( isEqualsDate(cacher, reqr) && cacher.getTitle().equals(reqr.getTitle()) ) {\r
2236                                 // 開始・終了日時とタイトルに変更がない場合は更新\r
2237                                 if (getDebug()) System.err.println("[DEBUG] Update PROG RSV");\r
2238                                 return UpdateRdEntryDT2(cacher,reqr);\r
2239                         }\r
2240                         else {\r
2241                                 // 開始・終了日時とタイトルに変更がある場合は削除して追加\r
2242                                 if (getDebug()) System.err.println("[DEBUG] Refresh PROG RSV");\r
2243                                 return UpdateRdEntryDT1(cacher,reqr);\r
2244                         }\r
2245                 }\r
2246         }\r
2247         \r
2248         /**\r
2249          * EPG予約を更新する\r
2250          */\r
2251         private boolean UpdateRdEntryTR(ReserveList cacher, ReserveList reqr) {\r
2252                 \r
2253                 // EDCBで更新する\r
2254                 int cnt = 1;\r
2255                 int cntMax = 2;\r
2256                 \r
2257                 ReserveList oldr = null;        // 本体にあった既存の予約情報\r
2258                 ReserveList newr = null;        // 更新後に取得しなおした新しい予約情報\r
2259                 \r
2260                 // 予約IDの検索\r
2261                 {\r
2262                         reportProgress(String.format("更新するEPG予約の予約IDを取得します(%d/%d).",cnt++,cntMax));\r
2263                         \r
2264                         // 予約IDを取得する\r
2265                         oldr = getRsvOnEdcbTR(cacher);\r
2266                         if ( oldr == null ) {\r
2267                                 return false;\r
2268                         }\r
2269                         \r
2270                         reportProgress("+更新される予約ID: "+oldr.getId());\r
2271                 }\r
2272                 \r
2273                 // 予約更新\r
2274                 {               \r
2275                         reportProgress(String.format("更新を実行します(%d/%d).",cnt++,cntMax));\r
2276                         \r
2277                         newr = _UpdateRdEntrySub(oldr, reqr);\r
2278                         if ( newr == null  ) {\r
2279                                 return false;\r
2280                         }\r
2281                         \r
2282                         // 本体から取得できない情報は引き継ぐ\r
2283                         copyAttributesMethod(reqr, newr);\r
2284                         \r
2285                         // 一発ヒットした場合は予約リストの更新が必要。再取得している場合は不要\r
2286                         int idx = getReserves().indexOf(cacher);\r
2287                         if ( idx >= 0 ) {\r
2288                                 getReserves().set(idx,newr);\r
2289                         }\r
2290                 }\r
2291                 \r
2292                 if ( isModified(cacher, newr) ) {\r
2293                         // ピンピンうるさいので実行OFFの予約の場合はだんまりで\r
2294                         errmsg = "EDCB番組表からの情報で内容が変更されました: "+newr.getStartDateTime()+"~"+newr.getZhh()+":"+newr.getZmm()+" "+newr.getTitle();\r
2295                 }\r
2296                 \r
2297                 return true;\r
2298         }\r
2299         \r
2300         /**\r
2301          * プログラム予約を更新する(開始・終了日時とタイトルに変更がない場合は更新)\r
2302          */\r
2303         private boolean UpdateRdEntryDT2(ReserveList cacher, ReserveList reqr) {\r
2304                 \r
2305                 // EDCBで更新する\r
2306                 int cnt = 1;\r
2307                 int cntMax = 2;\r
2308                 \r
2309                 ReserveList oldr = null;        // 本体にあった既存の予約情報\r
2310                 ReserveList newr = null;        // 更新後に取得しなおした新しい予約情報\r
2311                 \r
2312                 // EDCBの更新すべき予約IDを検索する ★EDCBは再起動すると予約IDが振り直しになるので必要!!\r
2313                 {\r
2314                         reportProgress(String.format("更新対象の予約を探します(%d/%d).",cnt++,cntMax));\r
2315                         \r
2316                         oldr = getRsvOnEdcbDT(cacher);\r
2317                         if ( oldr == null ) {\r
2318                                 errmsg = "予約一覧に更新対象が見つかりません。";\r
2319                                 return false;\r
2320                         }\r
2321                         \r
2322                         // 予約IDのみ更新\r
2323                         reportProgress("+更新される予約ID: "+oldr.getId());\r
2324                 }\r
2325                 \r
2326                 // 予約更新\r
2327                 {\r
2328                         reportProgress(String.format("プログラム予約を更新します(%d/%d).",cnt++,cntMax));\r
2329 \r
2330                         newr = _UpdateRdEntrySub(oldr, reqr);\r
2331                         if ( newr == null  ) {\r
2332                                 return false;\r
2333                         }\r
2334                         \r
2335                         // 本体から取得できない情報は引き継ぐ\r
2336                         copyAttributesMethod(reqr, newr);\r
2337                         \r
2338                         // 一発ヒットした場合は予約リストの更新が必要。再取得している場合は不要\r
2339                         int idx = getReserves().indexOf(cacher);\r
2340                         if ( idx >= 0 ) {\r
2341                                 getReserves().set(idx,newr);\r
2342                         }\r
2343                 }\r
2344                 \r
2345                 return true;\r
2346         }\r
2347         \r
2348         /**\r
2349          * プログラム予約を更新する(開始・終了日時とタイトルに変更がある場合は削除して追加)\r
2350          */\r
2351         private boolean UpdateRdEntryDT1(ReserveList cacher, ReserveList reqr) {\r
2352                 \r
2353                 reportProgress("プログラム予約を登録し直します.");\r
2354                 \r
2355                 // 削除して\r
2356                 if ( RemoveRdEntry(cacher.getId()) == null ) {\r
2357                         return(false);\r
2358                 }\r
2359                 \r
2360                 // 追加する\r
2361                 if ( ! PostRdEntry(reqr) ) {\r
2362                         errmsg += "予約が削除されたので登録しなおしてください。";\r
2363                 }\r
2364                 \r
2365                 return(true);\r
2366         }\r
2367 \r
2368         /**\r
2369          * 予約更新の共通部分\r
2370          */\r
2371         private ReserveList _UpdateRdEntrySub(ReserveList oldr, ReserveList reqr) {\r
2372                 \r
2373                 String pstr = genPoststrDTB(reqr);\r
2374                 String uri = "http://"+getIPAddr()+":"+getPortNo()+"/reservechg.html?id="+getRsvId(oldr.getId());\r
2375                 \r
2376                 System.err.println("URL: "+uri);\r
2377                 \r
2378                 String header = null;\r
2379                 String response = null;\r
2380                 for (int i=0; i<retryMax; i++) {\r
2381                         String[] d = reqPOST(uri, pstr, null);\r
2382                         header = d[0];\r
2383                         response = d[1];\r
2384                         if ( header != null && response == null ) {\r
2385                                 reportProgress("コネクションがリセットされました。リトライします。");\r
2386                                 CommonUtils.milSleep(1000);\r
2387                         }\r
2388                         else {\r
2389                                 break;\r
2390                         }\r
2391                 }\r
2392                 if ( header == null || response == null ) {\r
2393                         errmsg = "レコーダーが反応しません。";\r
2394                         return null;\r
2395                 }\r
2396                 if ( ! response.contains("予約を変更しました") ) {\r
2397                         errmsg = "更新に失敗しました。";\r
2398                         return null;\r
2399                 }\r
2400                 \r
2401                 // 更新後の情報を再取得\r
2402                 ReserveList newr = reqr.clone();\r
2403                 newr.setId(oldr.getId());\r
2404                 if ( ! getRsvDetailByReserveId(newr,0) ) {\r
2405                         errmsg = "更新後の情報を取得できませんでした。";\r
2406                         return null;\r
2407                 }\r
2408 \r
2409                 System.out.printf("\n<<< Message from RD >>> \"%s\"\n\n", "正常に更新できました。");\r
2410                 return newr;\r
2411         }\r
2412         \r
2413         \r
2414         /*******************************************************************************\r
2415          * 予約削除\r
2416          ******************************************************************************/\r
2417         \r
2418         @Override\r
2419         public ReserveList RemoveRdEntry(String delid) {\r
2420                 \r
2421                 System.out.println("Run: RemoveRdEntry()");\r
2422                 \r
2423                 errmsg = "";\r
2424                 \r
2425                 // おまじない\r
2426                 Authenticator.setDefault(new MyAuthenticator(getUser(), getPasswd()));\r
2427 \r
2428                 ReserveList delr = null;        // キャッシュ上の削除対象\r
2429                 ReserveList oldr = null;        // レコーダ上の削除対象\r
2430                 \r
2431                 // キャッシュから削除対象を探す\r
2432                 for ( ReserveList reserve : getReserves() )  {\r
2433                         if (reserve.getId().equals(delid)) {\r
2434                                 delr = reserve;\r
2435                                 break;\r
2436                         }\r
2437                 }\r
2438                 if (delr == null) {\r
2439                         return(null);\r
2440                 }\r
2441                 \r
2442                 // EDCBから削除対象を探す ★EDCBは再起動すると予約IDが振り直しになるので必要!!\r
2443                 reportProgress(String.format("削除する予約IDを取得します."));\r
2444                 \r
2445                 if ( ContentIdEDCB.isValid(delr.getContentId()) ) {\r
2446                         oldr = getRsvOnEdcbTR(delr);\r
2447                 }\r
2448                 else {\r
2449                         oldr = getRsvOnEdcbDT(delr);\r
2450                 }\r
2451                 if ( oldr == null ) {\r
2452                         errmsg = "レコーダ上に削除対象が見つかりません。";\r
2453                         return(null);\r
2454                 }\r
2455                 \r
2456                 reportProgress("+削除される予約ID: "+oldr.getId());\r
2457                 \r
2458                 // EDCBから削除する\r
2459                 String header;\r
2460                 String response;\r
2461 \r
2462                 {               \r
2463                         reportProgress("削除を実行します.");\r
2464                         String uri = "http://"+getIPAddr()+":"+getPortNo()+"/reservedel.html?id="+getRsvId(oldr.getId());\r
2465                         \r
2466                         System.err.println("URL: "+uri);\r
2467                         \r
2468                         header = response = null;\r
2469                         for (int i=0; i<retryMax; i++) {\r
2470                                 String[] d = reqPOST(uri, "", null);\r
2471                                 header = d[0];\r
2472                                 response = d[1];\r
2473                                 if ( header != null && response == null ) {\r
2474                                         reportProgress("コネクションがリセットされました。リトライします。");\r
2475                                         CommonUtils.milSleep(1000);\r
2476                                 }\r
2477                                 else {\r
2478                                         break;\r
2479                                 }\r
2480                         }\r
2481                         if ( header == null || response == null ) {\r
2482                                 errmsg = "レコーダーが反応しません。";\r
2483                                 return(null);\r
2484                         }\r
2485                         if ( ! response.contains("予約を削除しました") ) {\r
2486                                 errmsg = "削除に失敗しました。";\r
2487                                 return(null);\r
2488                         }\r
2489                 }\r
2490                 \r
2491                 // 予約リストを更新\r
2492                 getReserves().remove(delr);\r
2493                 \r
2494                 // キャッシュに保存(削除なので録画済みフラグは操作しなくてよい)\r
2495                 ReservesToFile(getReserves(), rsvedFile);\r
2496                 //setRecordedFlag();\r
2497                 \r
2498                 System.out.printf("\n<<< Message from RD >>> \"%s\"\n\n", "正常に削除できました。");\r
2499                 \r
2500                 return delr;\r
2501         }\r
2502         \r
2503         \r
2504         /*******************************************************************************\r
2505          * 予約用の部品\r
2506          ******************************************************************************/\r
2507         \r
2508         /**\r
2509          * 放送局と日付のチェック\r
2510          */\r
2511         private boolean PrePostCheck(ReserveList r) {\r
2512                 // 放送局\r
2513                 r.setChannel(cc.getCH_WEB2CODE(r.getCh_name()));\r
2514                 if ( r.getChannel() == null) {\r
2515                         errmsg = "【警告】Web番組表の放送局名「"+r.getCh_name()+"」をCHコードに変換できません。CHコード設定を修正してください。" ;\r
2516                         System.out.println(errmsg);\r
2517                         return(false);\r
2518                 }\r
2519                 \r
2520                 // 予約パターンID\r
2521                 // 次回予定日\r
2522                 // 録画長\r
2523                 // 開始日時・終了日時\r
2524                 r.setRec_pattern_id(getRec_pattern_Id(r.getRec_pattern()));\r
2525                 r.setRec_nextdate(CommonUtils.getNextDate(r));\r
2526                 r.setRec_min(CommonUtils.getRecMin(r.getAhh(),r.getAmm(),r.getZhh(),r.getZmm()));\r
2527                 getStartEndDateTime(r);\r
2528                 if ( r.getRec_pattern_id() != 11 ) {\r
2529                         errmsg = "日付指定しか利用出来ません。";\r
2530                         System.out.println(errmsg);\r
2531                         return(false) ;\r
2532                 }\r
2533                 \r
2534                 return true;\r
2535         }\r
2536         \r
2537         /**\r
2538          * プログラム予約の制限のチェック\r
2539          */\r
2540         private boolean PreProgResCheck(ReserveList r) {\r
2541                 if (\r
2542                                 getTextPittariFlag(r).equals(ITEM_JUST_ENABLE)\r
2543                         ) {\r
2544                         errmsg = "プログラム予約では次の指定はできません:ぴったり録画="+ITEM_JUST_ENABLE;\r
2545                         return(false) ;\r
2546                 }\r
2547                 \r
2548                 if (\r
2549                                 r.getPursues()\r
2550                         ) {\r
2551                         errmsg = "プログラム予約では次の指定はできないので規定値に変更しました:番組追従="+ITEM_YES;\r
2552                         r.setPursues(false);\r
2553                         //return(false) ;\r
2554                 }\r
2555                 \r
2556                 return true;\r
2557         }\r
2558         \r
2559         /**\r
2560          * EDCB予約一覧から操作対象を探すのです(EPG予約版)\r
2561          * @see #isEqualsTR(ReserveList, ReserveList, int)\r
2562          * @see #getRsvOnEdcbDT(ReserveList)\r
2563          */\r
2564         private ReserveList getRsvOnEdcbTR(ReserveList origr) {\r
2565                 \r
2566                 // 予約IDを試してみる(EDCBがリブートしていなければこれでOKなはず)\r
2567                 if ( origr.getId() != null && origr.getId().length() > 0 ) {\r
2568                         ReserveList newr = origr.clone();\r
2569                         if ( getRsvDetailByReserveId(newr,0) && isEqualsTR(origr, newr, -1) ) {\r
2570                                 //System.out.println("+-一致する予約です(予約ID直接): "+newr.getId());\r
2571                                 return newr;\r
2572                         }\r
2573                 }\r
2574                 \r
2575                 // 番組IDを試してみる(重複予約されていなければこれで大丈夫なはず)\r
2576                 if ( origr.getContentId() != null && ContentIdEDCB.isValid(origr.getContentId()) ) {\r
2577                         ReserveList newr = origr.clone();\r
2578                         if ( getRsvDetailByContentId(newr,0) && isEqualsTR(origr, newr, 0) ) {\r
2579                                 //System.out.println("+-一致する予約です(番組ID直接): "+newr.getId());\r
2580                                 return newr;\r
2581                         }\r
2582                 }\r
2583 \r
2584                 // 一覧取得しなおし(3.17.5b)\r
2585                 ArrayList<ReserveList> rl = new ArrayList<ReserveList>();\r
2586                 if ( ! getRsvListAPI(rl) ) {\r
2587                         errmsg = "予約一覧の取得に失敗しました。";\r
2588                         return null;\r
2589                 }\r
2590 \r
2591                 // 置き換えていいよ\r
2592                 setReserves(rl);\r
2593 \r
2594                 // 一覧から該当する予約を探す\r
2595                 int idx=1;\r
2596                 for ( ReserveList newr : rl ) {\r
2597                         if ( isEqualsTR(origr, newr, idx++) ) {\r
2598                                 return newr;\r
2599                         }\r
2600                 }\r
2601                 \r
2602                 errmsg = "予約IDがみつかりません。";\r
2603                 return null;\r
2604         }\r
2605         \r
2606         /**\r
2607          * 同じEPG予約かどうかしらべる\r
2608          */\r
2609         private boolean isEqualsTR(ReserveList origr, ReserveList newr, Integer idx) {\r
2610                 \r
2611                 // 放送局が一緒で、開始日時が近いかどうか(旧情報vs一覧)\r
2612                 if ( ! isLikesRsvOnList(origr, newr) ) {\r
2613                         return false;\r
2614                 }\r
2615                 \r
2616                 // EPG予約かどうか(詳細)\r
2617                 if ( ! ContentIdEDCB.isValid(newr.getContentId()) ) {\r
2618                         if ( idx != null ) System.out.println("+-そっくりですがEPG予約ではありません: "+newr.getId());\r
2619                         return false;\r
2620                 }\r
2621                 \r
2622                 // おなじ番組かどうか(旧情報vs一覧)\r
2623                 if ( ! origr.getContentId().equals(newr.getContentId()) ) {\r
2624                         if ( idx != null ) System.out.println("+-そっくりですが別の番組です: "+newr.getId());\r
2625                         return false;\r
2626                 }\r
2627                 \r
2628                 // チューナー指定が等しいかどうか(旧情報vs一覧)\r
2629                 if ( ! origr.getTuner().equals(newr.getTuner()) ) {\r
2630                         if ( idx != null ) System.out.println("+-そっくりですが異なる予約です(使用するチューナーが異なります): "+newr.getId());\r
2631                         return false;\r
2632                 }\r
2633                 \r
2634                 // 時間移動も確認しておくか\r
2635                 if ( isEqualsDate(origr, newr) ) {\r
2636                         if ( idx != null ) {\r
2637                                 if ( idx == -1 ) {\r
2638                                         System.out.println("+-一致する予約です(予約ID直接): "+newr.getId());\r
2639                                 }\r
2640                                 else if ( idx == 0 ) {\r
2641                                         System.out.println("+-一致する予約です(番組ID直接): "+newr.getId());\r
2642                                 }\r
2643                                 else {\r
2644                                         System.out.println("+-一致する予約です(間接)["+idx+"]: "+newr.getId());\r
2645                                 }\r
2646                         }\r
2647                 }\r
2648                 else {\r
2649                         System.out.println("+-一致する予約のようです(時間が移動しています)["+idx+"]: "+newr.getId());\r
2650                 }\r
2651                 \r
2652                 return true;\r
2653         }\r
2654         \r
2655         /**\r
2656          * EDCB予約一覧から操作対象を探すのです(プログラム予約版)<BR>\r
2657          * ※一発ヒットしたものはキャッシュに乗らないので注意\r
2658          * @see #isEqualsDT(ReserveList, ReserveList, int)\r
2659          * @see #getRsvOnEdcbTR(ReserveList)\r
2660          */\r
2661         private ReserveList getRsvOnEdcbDT(ReserveList origr) {\r
2662                 \r
2663                 // 予約IDを試してみる(EDCBがリブートしていなければこれでOKなはず)\r
2664                 if ( origr.getId() != null && origr.getId().length() > 0 ) {\r
2665                         ReserveList newr = origr.clone();\r
2666                         if ( getRsvDetailByReserveId(newr,0) && isEqualsDT(origr, newr, 0) ) {\r
2667                                 //System.out.println("+-一致する予約です(番組ID直接): "+newr.getId());\r
2668                                 return newr;\r
2669                         }\r
2670                 }\r
2671 \r
2672                 // 予約IDは固定ではないので再度取得しなおさないと(3.17.5b変更)\r
2673                 ArrayList<ReserveList> rl = new ArrayList<ReserveList>();\r
2674                 if ( ! getRsvListAPI(rl) ) {\r
2675                         errmsg = "予約一覧の取得に失敗しました。";\r
2676                         return null;\r
2677                 }\r
2678 \r
2679                 // 置き換えていいよ\r
2680                 setReserves(rl);\r
2681                 \r
2682                 // 一覧から該当する予約を探す\r
2683                 int idx=0;\r
2684                 for ( ReserveList newr : rl ) {\r
2685                         if ( isEqualsDT(origr, newr, idx++) ) {\r
2686                                 return newr;\r
2687                         }\r
2688                 }\r
2689                 \r
2690                 errmsg = "予約IDが見つかりません。";\r
2691                 return null;\r
2692         }\r
2693         \r
2694         /**\r
2695          * 同じプログラム予約かどうかしらべる\r
2696          */\r
2697         private boolean isEqualsDT(ReserveList origr, ReserveList newr, Integer idx) {\r
2698                 \r
2699                 // 放送局がいっしょで、開始日時・終了時刻が等しいかどうか(旧情報vs一覧)\r
2700                 if ( ! isEqualsRsvOnList(origr, newr) ) {\r
2701                         return false;\r
2702                 }\r
2703                 \r
2704                 // プログラム予約かどうか\r
2705                 if ( ContentIdEDCB.isValid(newr.getContentId()) ) {\r
2706                         if ( idx != null ) System.out.println("+-そっくりですがプログラム予約ではありません: "+newr.getId());\r
2707                         return false;\r
2708                 }\r
2709                 \r
2710                 // チューナー指定が等しいかどうか(旧情報vs一覧)\r
2711                 if ( ! origr.getTuner().equals(newr.getTuner()) ) {\r
2712                         if ( idx != null ) System.out.println("+-そっくりですが異なる予約です(使用するチューナーが異なります): "+newr.getId());\r
2713                         return false;\r
2714                 }\r
2715                 \r
2716                 if ( idx != null ) {\r
2717                         if ( idx == 0 ) {\r
2718                                 System.out.println("+-一致する予約です(予約ID直接): "+newr.getId());\r
2719                         }\r
2720                         else {\r
2721                                 System.out.println("+-一致する予約です(間接)["+idx+"]: "+newr.getId());\r
2722                         }\r
2723                 }\r
2724                 \r
2725                 return true;\r
2726         }\r
2727 \r
2728         /**\r
2729          * 古い予約一覧から情報を引き継ぐ\r
2730          */\r
2731         private void copyAttributesAllList( ArrayList<ReserveList> oldrl, ArrayList<ReserveList> newrl ) {\r
2732                 \r
2733                 // 予約一覧の再取得があった\r
2734                 for ( ReserveList newr : newrl ) {\r
2735                         if ( newr.getContentId() != null ) {\r
2736                                 for ( ReserveList oldr : oldrl ) {\r
2737                                         if ( oldr.getContentId() != null && isEqualsTR(oldr, newr, null) ) {\r
2738                                                 copyAttributesMethod(oldr, newr);\r
2739                                         }\r
2740                                 }\r
2741                         }\r
2742                         else {\r
2743                                 for ( ReserveList oldr : oldrl ) {\r
2744                                         if ( oldr.getContentId() == null && isEqualsDT(oldr, newr, null) ) {\r
2745                                                 copyAttributesMethod(oldr, newr);\r
2746                                         }\r
2747                                 }\r
2748                         }\r
2749                 }\r
2750                 \r
2751         }\r
2752         private void copyAttributesMethod( ReserveList oldr, ReserveList newr ) {\r
2753                 newr.setRec_genre(oldr.getRec_genre());\r
2754                 newr.setRec_subgenre(oldr.getRec_subgenre());\r
2755                 setTextPresetID(newr, getTextPresetID(oldr));\r
2756         }\r
2757         \r
2758         \r
2759         /* ここまで */\r
2760         \r
2761         \r
2762         \r
2763 \r
2764         \r
2765         \r
2766         /*******************************************************************************\r
2767          * 非公開メソッド\r
2768          ******************************************************************************/\r
2769 \r
2770         //\r
2771         private String genPoststrEPGA(ReserveList r) {\r
2772                 StringBuilder sb = new StringBuilder();\r
2773                 try {\r
2774                         sb.append("presetID="+text2value(getListPresetID(),getTextPresetID(r))+"&");\r
2775                         sb.append("onid="+Integer.decode("0x"+r.getContentId().substring(5,9))+"&");\r
2776                         sb.append("tsid="+Integer.decode("0x"+r.getContentId().substring(9,13))+"&");\r
2777                         sb.append("sid="+Integer.decode("0x"+r.getContentId().substring(13,17))+"&");\r
2778                         sb.append("evid="+Integer.decode("0x"+r.getContentId().substring(17,21)));\r
2779                 }\r
2780                 catch ( Exception e ) {\r
2781                         e.printStackTrace();\r
2782                 }\r
2783                 return sb.toString();\r
2784         }\r
2785         private String genPoststrEPGB(ReserveList r) {\r
2786                 StringBuilder sb = new StringBuilder();\r
2787                 sb.append(genPoststrEPGA(r)+"&");\r
2788                 sb.append(genPoststrCom(r));\r
2789                 return sb.toString();\r
2790         }\r
2791         \r
2792         //\r
2793         private String genPoststrDTCom(ReserveList r) {\r
2794                 StringBuilder sb = new StringBuilder();\r
2795                 \r
2796                 // 日付指定しか対応してないが…\r
2797                 GregorianCalendar cal = CommonUtils.getCalendar(r.getRec_nextdate().substring(0,10));\r
2798                 sb.append("sdy="+cal.get(Calendar.YEAR)+"&");\r
2799                 sb.append("sdm="+(cal.get(Calendar.MONTH)+1)+"&");\r
2800                 sb.append("sdd="+cal.get(Calendar.DATE)+"&");\r
2801                 sb.append("sth="+Integer.valueOf(r.getAhh())+"&");\r
2802                 sb.append("stm="+Integer.valueOf(r.getAmm())+"&");\r
2803                 //\r
2804                 if ( r.getAhh().compareTo(r.getZhh()) > 0 ) {\r
2805                         cal.add(Calendar.DATE, 1);\r
2806                 }\r
2807                 sb.append("edy="+cal.get(Calendar.YEAR)+"&");\r
2808                 sb.append("edm="+(cal.get(Calendar.MONTH)+1)+"&");\r
2809                 sb.append("edd="+cal.get(Calendar.DATE)+"&");\r
2810                 sb.append("eth="+Integer.valueOf(r.getZhh())+"&");\r
2811                 sb.append("etm="+Integer.valueOf(r.getZmm()));\r
2812                 \r
2813                 return sb.toString();\r
2814         }\r
2815         private String genPoststrDTA(ReserveList r) {\r
2816                 StringBuilder sb = new StringBuilder();\r
2817                 try {\r
2818                         //sb.append("presetID="+text2value(getListPresetID(),getTextPresetID(r))+"&");\r
2819                         sb.append("serviceID="+cc.getCH_WEB2CODE(r.getCh_name())+"&");\r
2820                         sb.append("pgname="+URLEncoder.encode(r.getTitle(),thisEncoding)+"&");\r
2821                         sb.append(genPoststrDTCom(r));\r
2822                 } catch (UnsupportedEncodingException e) {\r
2823                         e.printStackTrace();\r
2824                 }\r
2825                 \r
2826                 return sb.toString();\r
2827         }\r
2828         private String genPoststrDTB(ReserveList r) {\r
2829                 StringBuilder sb = new StringBuilder();\r
2830                 try {\r
2831                         sb.append("serviceID="+cc.getCH_WEB2CODE(r.getCh_name())+"&");\r
2832                         sb.append("pgname="+URLEncoder.encode(r.getTitle(),thisEncoding)+"&");\r
2833                         sb.append(genPoststrDTCom(r)+"&");\r
2834                         sb.append(genPoststrCom(r));\r
2835                 } catch (UnsupportedEncodingException e) {\r
2836                         e.printStackTrace();\r
2837                 }\r
2838                 \r
2839                 return sb.toString();\r
2840         }\r
2841         \r
2842         //                      \r
2843         private String genPoststrCom(ReserveList r) {\r
2844                 // EPG・プログラム予約共通\r
2845                 StringBuilder sb = new StringBuilder();\r
2846                 try {\r
2847                         sb.append("presetID="+text2value(getListPresetID(),getTextPresetID(r))+"&");\r
2848                         if ( r.getExec() ) {\r
2849                                 sb.append("recMode="+text2value(getListRecMode(),getTextRecMode(r))+"&");\r
2850                         }\r
2851                         else {\r
2852                                 sb.append("recMode="+VALUE_REC_MODE_DISABLE+"&");\r
2853                         }\r
2854                         if ( r.getPursues() ) {\r
2855                                 sb.append("tuijyuuFlag="+VALUE_TRACE_ENABLE+"&");\r
2856                         }\r
2857                         else {\r
2858                                 sb.append("tuijyuuFlag="+VALUE_TRACE_DISABLE+"&");\r
2859                         }\r
2860                         sb.append("priority="+text2value(getListPriority(),getTextPriority(r))+"&");\r
2861                         sb.append("pittariFlag="+text2value(getListPittariFlag(),getTextPittariFlag(r))+"&");\r
2862                         sb.append("suspendMode="+text2value(getListSuspendMode(),getTextSuspendMode(r))+"&");\r
2863                         if ( getTextStartMargine(r).equals(ITEM_MARGINE_DEFAULT) || getTextEndMargine(r).equals(ITEM_MARGINE_DEFAULT) ) {\r
2864                                 sb.append("useDefMargineFlag=1&");\r
2865                                 sb.append("startMargine=0&");\r
2866                                 sb.append("endMargine=0&");\r
2867                         }\r
2868                         else {\r
2869                                 sb.append("startMargine="+text2value(getListStartMargine(),getTextStartMargine(r))+"&");\r
2870                                 sb.append("endMargine="+text2value(getListEndMargine(),getTextEndMargine(r))+"&");\r
2871                         }\r
2872                         {\r
2873                                 String s = getTextServiceMode(r);\r
2874                                 if ( s.equals(ITEM_SERVMOCE_DEFAULT) ) {\r
2875                                         sb.append("serviceMode=0&");\r
2876                                 }\r
2877                                 else {\r
2878                                         if ( s.equals(ITEM_SERVMOCE_SUBT) || s.equals(ITEM_SERVMOCE_SUBTCARO) ) {\r
2879                                                 sb.append("serviceMode_1=0&");\r
2880                                         }\r
2881                                         if ( s.equals(ITEM_SERVMOCE_CARO) || s.equals(ITEM_SERVMOCE_SUBTCARO) ) {\r
2882                                                 sb.append("serviceMode_2=0&");\r
2883                                         }\r
2884                                 }\r
2885                         }\r
2886                         sb.append("tunerID="+text2value(getListTunerID(),getTextTunerID(r))+"&");\r
2887                         if ( getTextContinueRecFlag(r).equals(ITEM_YES) ) {\r
2888                                 sb.append("continueRecFlag=1&");\r
2889                         }\r
2890                         if ( getTextRebootFlag(r).equals(ITEM_YES) ) {\r
2891                                 sb.append("rebootFlag=1&");\r
2892                         }\r
2893                         if ( getTextPartialRecFlag(r).equals(ITEM_YES) ) {\r
2894                                 sb.append("partialRecFlag=1&");\r
2895                         }\r
2896                         \r
2897                         // オプショナル\r
2898                         {\r
2899                                 String val = r.getHidden_params().get(RETVAL_KEY_RECFOLDERCOUNT);\r
2900                                 sb.append("recFolderCount=");\r
2901                                 sb.append((val!=null)?(val):("0"));\r
2902                                 sb.append("&");\r
2903                                 \r
2904                                 val = r.getHidden_params().get(RETVAL_KEY_PARTIALFOLDERCOUNT);\r
2905                                 sb.append("partialFolderCount=");\r
2906                                 sb.append((val!=null)?(val):("0"));\r
2907                         }\r
2908                 }\r
2909                 catch ( Exception e ) {\r
2910                         e.printStackTrace();\r
2911                 }\r
2912                 \r
2913                 return sb.toString();\r
2914         }\r
2915         \r
2916         //\r
2917         private void setSettingRecMargin(ArrayList<TextValueSet> tvs) {\r
2918                 tvs.clear();\r
2919                 add2tvs(tvs,ITEM_MARGINE_DEFAULT,VALUE_MARGINE_DEFAULT);\r
2920                 for (int i=0; i<=90; i++) {\r
2921                         add2tvs(tvs,String.valueOf(i),String.valueOf(i));\r
2922                 }\r
2923         }\r
2924         private void setSettingServiceMode(ArrayList<TextValueSet> tvs) {\r
2925                 tvs.clear();\r
2926                 add2tvs(tvs,ITEM_SERVMOCE_DEFAULT,VALUE_SERVMOCE_DEFAULT);\r
2927                 add2tvs(tvs,ITEM_SERVMOCE_SUBT,VALUE_SERVMOCE_SUBT);\r
2928                 add2tvs(tvs,ITEM_SERVMOCE_CARO,VALUE_SERVMOCE_CARO);\r
2929                 add2tvs(tvs,ITEM_SERVMOCE_SUBTCARO,VALUE_SERVMOCE_SUBTCARO);\r
2930                 add2tvs(tvs,ITEM_SERVMOCE_NONE,VALUE_SERVMOCE_NONE);\r
2931         }\r
2932         private void setSettingNoYes(ArrayList<TextValueSet> tvs) {\r
2933                 tvs.clear();\r
2934                 add2tvs(tvs,ITEM_NO,VALUE_NO);\r
2935                 add2tvs(tvs,ITEM_YES,VALUE_YES);\r
2936         }\r
2937         private void setSettingRecType(ArrayList<TextValueSet> tvs) {\r
2938                 tvs.clear();\r
2939                 add2tvs(tvs,ITEM_REC_TYPE_EPG,VALUE_REC_TYPE_EPG);\r
2940                 add2tvs(tvs,ITEM_REC_TYPE_PROG,VALUE_REC_TYPE_PROG);\r
2941         }\r
2942         //\r
2943         private void setSettingChCodeValue(ArrayList<TextValueSet> tvsValue, ArrayList<TextValueSet> tvsType, String key, String res) {\r
2944                 \r
2945                 HashMap<String, String> typ = new HashMap<String, String>();\r
2946                 typ.put("地デジ", "uvd");\r
2947                 typ.put("BS", "bsd");\r
2948                 typ.put("","csd");\r
2949                 \r
2950                 tvsValue.clear();\r
2951                 tvsType.clear();\r
2952                 Matcher mb = Pattern.compile("<select name=\""+key+"\">([\\s\\S]+?)</select>").matcher(res);\r
2953                 if (mb.find()) {\r
2954                         Matcher mc = Pattern.compile("<option value=\"([^\"]*?)\"(\\s*selected\\s*)?>(.+?)\\((.+?)\\)\\n").matcher(mb.group(1));\r
2955                         while (mc.find()) {\r
2956                                 // ワンセグは対象外\r
2957                                 if (mc.group(4).equals("ワンセグ")) {\r
2958                                         continue;\r
2959                                 }\r
2960                                 \r
2961                                 String chname = mc.group(3);\r
2962                                 Long chid = 0L;\r
2963                                 \r
2964                                 // 難視聴対策放送\r
2965                                 try {\r
2966                                         chid = Long.valueOf(mc.group(1));\r
2967                                         Long tsid = (chid & 0x0000FFFF0000L);\r
2968                                         if ( tsid == 0x000043100000L || tsid == 0x000043110000L ) {\r
2969                                                 chname = TEXT_NANSHICHO_HEADER+chname;\r
2970                                                 System.out.println("[DEBUG] "+chname);\r
2971                                         }\r
2972                                 }\r
2973                                 catch (NumberFormatException e) {\r
2974                                         continue;\r
2975                                 }\r
2976                                 \r
2977                                 // 重複する放送局名は対象外\r
2978                                 boolean dup = false;\r
2979                                 for ( TextValueSet t : tvsValue ) {\r
2980                                         if ( t.getText().equals(chname) ) {\r
2981                                                 dup = true;\r
2982                                         }\r
2983                                 }\r
2984                                 if (dup) {\r
2985                                         continue;\r
2986                                 }\r
2987                                 \r
2988                                 // 放送局ID順でソートして追加\r
2989                                 {\r
2990                                         int n = 0;\r
2991                                         for ( ; n<tvsValue.size(); n++ ) {\r
2992                                                 if ( Long.valueOf(tvsValue.get(n).getValue()) > Long.valueOf(chid) ) {\r
2993                                                         break;\r
2994                                                 }\r
2995                                         }\r
2996                                         add2tvs(n,tvsValue,chname,mc.group(1));\r
2997                                 }\r
2998 \r
2999                                 // 地デジでもBSでもないものは全部CSあつかい\r
3000                                 {\r
3001                                         String val = typ.get(mc.group(4));\r
3002                                         if (val == null) {\r
3003                                                 val = typ.get("");\r
3004                                         }\r
3005                                         add2tvs(tvsType,chname,val);\r
3006                                 }\r
3007                         }\r
3008                 }\r
3009                 \r
3010                 System.err.println("=== CHコード一覧 for EDCB ===");\r
3011                 System.err.println("放送局 : \"レコーダの放送局名\",\"放送局コード\"");\r
3012                 System.err.println("=============================");\r
3013                 \r
3014                 for ( TextValueSet tv : tvsValue ) {\r
3015                         System.err.println(String.format("%-20s : \"%s\",\"%s\"",tv.getText(),tv.getValue(),tv.getValue()));\r
3016                 }\r
3017                 System.err.println("=============================");\r
3018         }\r
3019         //\r
3020         protected void setSettingEtc(ArrayList<TextValueSet> tvs, String key, int typ, String res) {\r
3021                 tvs.clear();\r
3022                 Matcher mb = Pattern.compile("<select name=\""+key+"\">([\\s\\S]+?)</select>").matcher(res);\r
3023                 if (mb.find()) {\r
3024                         Matcher mc = Pattern.compile("<option value=\"([^\"]*?)\"(\\s*selected\\s*)?>(.*?)\\n").matcher(mb.group(1));\r
3025                         while (mc.find()) {\r
3026                                 TextValueSet t = add2tvs(tvs,mc.group(3),mc.group(1));\r
3027                                 if (mc.group(2) != null) {\r
3028                                         t.setDefval(true);\r
3029                                 }\r
3030                         }\r
3031                 }\r
3032         }\r
3033         \r
3034         // 予約情報同志を比較する\r
3035         private boolean isModified(ReserveList o, ReserveList r) {\r
3036                 return ! (isEqualsDate(o, r) && o.getTitle().equals(r.getTitle()));\r
3037         }\r
3038         private boolean isEqualsRsvOnDetail(ReserveList o, ReserveList r) {\r
3039                 // ここまで一緒なら同じ予約情報だろ\r
3040                 return (isEqualsRsvOnList(o, r) && o.getTuner().equals(r.getTuner()));\r
3041         }\r
3042         private boolean isEqualsRsvOnList(ReserveList o, ReserveList r) {\r
3043                 // ここまで一緒なら同じ予約情報だろ\r
3044                 return (isEqualsDate(o, r) && o.getChannel().equals(r.getChannel()));\r
3045         }\r
3046         private boolean isEqualsDate(ReserveList o, ReserveList r) {\r
3047                 return (o.getStartDateTime().equals(r.getStartDateTime()) && o.getEndDateTime().equals(r.getEndDateTime()));\r
3048         }\r
3049         private boolean isLikesRsvOnList(ReserveList o, ReserveList r) {\r
3050                 // ここまで一緒なら親戚の予約情報だろ\r
3051                 return (isLikesDate(o, r) && o.getChannel().equals(r.getChannel()));\r
3052         }\r
3053         private boolean isLikesDate(ReserveList o, ReserveList r) {\r
3054                 return (CommonUtils.getDiffDateTime(o.getStartDateTime(), r.getStartDateTime()) < likersvrange);\r
3055         }\r
3056 }\r