OSDN Git Service

クラスメンバ定義順統一
[jindolf/JinArchiver.git] / src / main / java / jp / sourceforge / jindolf / archiver / VillageData.java
1 /*\r
2  * village data\r
3  *\r
4  * License : The MIT License\r
5  * Copyright(c) 2008 olyutorskii\r
6  */\r
7 \r
8 package jp.sourceforge.jindolf.archiver;\r
9 \r
10 import java.io.IOException;\r
11 import java.io.Writer;\r
12 import java.util.Collections;\r
13 import java.util.LinkedList;\r
14 import java.util.List;\r
15 import jp.sourceforge.jindolf.corelib.DisclosureType;\r
16 import jp.sourceforge.jindolf.corelib.LandDef;\r
17 import jp.sourceforge.jindolf.corelib.PeriodType;\r
18 import jp.sourceforge.jindolf.corelib.PreDefAvatar;\r
19 \r
20 /**\r
21  * 村のデータモデル。\r
22  * villageタグに相当。\r
23  */\r
24 public class VillageData{\r
25 \r
26     private final List<PeriodResource> resourceList;\r
27 \r
28     private final LandDef landDef;\r
29     private final int villageId;\r
30     private final String baseUri;\r
31 \r
32     private String fullName = "";\r
33     private int commitHour = -1;\r
34     private int commitMinute = -1;\r
35     private String graveIconUri;\r
36 \r
37     private final List<AvatarData> avatarList = new LinkedList<AvatarData>();\r
38     private int undefAvatarNo = 1;\r
39 \r
40     private final List<PeriodData> periodList = new LinkedList<PeriodData>();\r
41 \r
42 \r
43     /**\r
44      * コンストラクタ。\r
45      * @param resourceList PeriodResource並び\r
46      */\r
47     public VillageData(List<PeriodResource> resourceList){\r
48         super();\r
49 \r
50         validatePeriodResource(resourceList);\r
51 \r
52         this.resourceList = new LinkedList<PeriodResource>(resourceList);\r
53 \r
54         PeriodResource resource1st = this.resourceList.get(0);\r
55         this.landDef   = resource1st.getLandDef();\r
56         this.villageId = resource1st.getVillageId();\r
57         this.baseUri = getBaseUri(this.resourceList);\r
58 \r
59         return;\r
60     }\r
61 \r
62 \r
63     /**\r
64      * PeriodResourceの組が正当かチェックする。\r
65      * <ul>\r
66      * <li>全て同じ国に属していなければならない\r
67      * <li>全て同じ村に属していなければならない\r
68      * <li>日付は0から始まる連続した数値でなければならない\r
69      * <li>プロローグで始まらなければならない\r
70      * <li>エピローグで終わらなければならない\r
71      * <li>進行日はプロローグとエピローグに挟まれていなければならない\r
72      * </ul>\r
73      * @param list PeriodResource並び\r
74      * @throws IllegalArgumentException 引数が正当でない\r
75      */\r
76     public static void validatePeriodResource(List<PeriodResource> list)\r
77             throws IllegalArgumentException{\r
78         LandDef landDef = null;\r
79         int villageId = -1;\r
80         int lastDay = -1;\r
81         PeriodType periodType = null;\r
82 \r
83         for(PeriodResource resource : list){\r
84             if(landDef == null){\r
85                 landDef = resource.getLandDef();\r
86             }else if(resource.getLandDef() != landDef){\r
87                 throw new IllegalArgumentException();\r
88             }\r
89 \r
90             if(villageId < 0){\r
91                 villageId = resource.getVillageId();\r
92             }else if(resource.getVillageId() != villageId){\r
93                 throw new IllegalArgumentException();\r
94             }\r
95 \r
96             if(lastDay < 0){\r
97                 lastDay = resource.getDay();\r
98                 if(lastDay != 0) throw new IllegalArgumentException();\r
99             }else{\r
100                 if(resource.getDay() != lastDay + 1){\r
101                     throw new IllegalArgumentException();\r
102                 }\r
103                 lastDay = resource.getDay();\r
104             }\r
105 \r
106             if(periodType == null){\r
107                 periodType = resource.getPeriodType();\r
108                 if(periodType != PeriodType.PROLOGUE){\r
109                     throw new IllegalArgumentException();\r
110                 }\r
111                 if(lastDay != 0) throw new IllegalArgumentException();\r
112             }else if(periodType == PeriodType.PROLOGUE){\r
113                 periodType = resource.getPeriodType();\r
114                 if(periodType != PeriodType.PROGRESS){\r
115                     throw new IllegalArgumentException();\r
116                 }\r
117             }else if(periodType == PeriodType.PROGRESS){\r
118                 periodType = resource.getPeriodType();\r
119             }else if(periodType == PeriodType.EPILOGUE){\r
120                 throw new IllegalArgumentException();\r
121             }\r
122         }\r
123 \r
124         if(lastDay < 0) throw new IllegalArgumentException();\r
125         if(periodType != PeriodType.EPILOGUE){\r
126             throw new IllegalArgumentException();\r
127         }\r
128 \r
129         return;\r
130     }\r
131 \r
132     /**\r
133      * 全PeriodResourceから、共通するベースURIを抽出する。\r
134      * @param list PeriodResource並び\r
135      * @return ベースURI文字列\r
136      * @throws IllegalArgumentException ベースURIが一致していない\r
137      */\r
138     public static String getBaseUri(List<PeriodResource> list)\r
139             throws IllegalArgumentException{\r
140         String result = null;\r
141 \r
142         for(PeriodResource resource : list){\r
143             String urlText = resource.getOrigUrlText();\r
144             urlText = urlText.replaceAll("[^/]*$", "");\r
145             if(result == null){\r
146                 result = urlText;\r
147             }else{\r
148                 if( ! result.equals(urlText) ){\r
149                     throw new IllegalArgumentException();\r
150                 }\r
151             }\r
152         }\r
153 \r
154         return result;\r
155     }\r
156 \r
157     /**\r
158      * 国情報を取得する。\r
159      * @return 国情報\r
160      */\r
161     public LandDef getLandDef(){\r
162         return this.landDef;\r
163     }\r
164 \r
165     /**\r
166      * 村IDを取得する。\r
167      * @return 村ID\r
168      */\r
169     public int getVillageId(){\r
170         return this.villageId;\r
171     }\r
172 \r
173     /**\r
174      * ベースURIを取得する。\r
175      * @return ベースURI\r
176      */\r
177     public String getBaseUri(){\r
178         return this.baseUri;\r
179     }\r
180 \r
181     /**\r
182      * 村フルネームを取得する。\r
183      * @return 村フルネーム\r
184      */\r
185     public String getFullName(){\r
186         return this.fullName;\r
187     }\r
188 \r
189     /**\r
190      * 村フルネームを設定する。\r
191      * @param fullName 村フルネーム\r
192      */\r
193     public void setFullName(String fullName){\r
194         this.fullName = fullName;\r
195         return;\r
196     }\r
197 \r
198     /**\r
199      * 更新時を取得する。\r
200      * @return 更新時\r
201      */\r
202     public int getCommitHour(){\r
203         return this.commitHour;\r
204     }\r
205 \r
206     /**\r
207      * 更新時を設定する。\r
208      * @param commitHour 更新時\r
209      */\r
210     public void setCommitHour(int commitHour){\r
211         this.commitHour = commitHour;\r
212         return;\r
213     }\r
214 \r
215     /**\r
216      * 更新分を取得する。\r
217      * @return 更新分\r
218      */\r
219     public int getCommitMinute(){\r
220         return this.commitMinute;\r
221     }\r
222 \r
223     /**\r
224      * 更新分を設定する。\r
225      * @param commitMinute 更新分\r
226      */\r
227     public void setCommitMinute(int commitMinute){\r
228         this.commitMinute = commitMinute;\r
229         return;\r
230     }\r
231 \r
232     /**\r
233      * 墓アイコンURIを取得する。\r
234      * @return 墓アイコンURI文字列\r
235      */\r
236     public String getGraveIconUri(){\r
237         if(this.graveIconUri == null){\r
238             return this.landDef.getTombFaceIconURI().toASCIIString();\r
239         }\r
240         return this.graveIconUri;\r
241     }\r
242 \r
243     /**\r
244      * 墓アイコンURI文字列を設定する。\r
245      * @param graveIconUri 墓アイコンURI文字列\r
246      */\r
247     public void setGraveIconUri(String graveIconUri){\r
248         this.graveIconUri = graveIconUri;\r
249         return;\r
250     }\r
251 \r
252     /**\r
253      * 全Periodの開示状況から総合開示状況を算出する。\r
254      * @return 公開状況\r
255      */\r
256     public DisclosureType getDisclosureType(){\r
257         DisclosureType result = DisclosureType.COMPLETE;\r
258 \r
259         for(PeriodData period : this.periodList){\r
260             DisclosureType type = period.getDisclosureType();\r
261             switch(type){\r
262             case HOT:\r
263                 return DisclosureType.HOT;\r
264             case UNCOMPLETE:\r
265                 result = DisclosureType.UNCOMPLETE;\r
266                 break;\r
267             default:\r
268                 break;\r
269             }\r
270         }\r
271 \r
272         return result;\r
273     }\r
274 \r
275     /**\r
276      * Periodモデルを追加する。\r
277      * @param period Periodモデル\r
278      */\r
279     public void addPeriodData(PeriodData period){\r
280         this.periodList.add(period);\r
281         return;\r
282     }\r
283 \r
284     /**\r
285      * PeriodResourcenar並びを取得する。\r
286      * @return PeriodResource並び\r
287      */\r
288     public List<PeriodResource> getPeriodResourceList(){\r
289         return Collections.unmodifiableList(this.resourceList);\r
290     }\r
291 \r
292     /**\r
293      * 未知の新規Avatarを生成する。\r
294      * ※ F1556村などへの対処。\r
295      * Avatarのフルネーム、短縮名、識別子が設定される。\r
296      * @param avfullName Avatarのフルネーム\r
297      * @return 新規Avatarモデル\r
298      */\r
299     public AvatarData createAvatar(String avfullName){\r
300         AvatarData avatar = new AvatarData();\r
301 \r
302         avatar.setFullName(avfullName);\r
303 \r
304         String[] token = avfullName.split("\\s");\r
305         String shortName = token[token.length - 1];\r
306         avatar.setShortName(shortName);\r
307 \r
308         String avatarId = "ukavatar" + this.undefAvatarNo;\r
309         this.undefAvatarNo++;\r
310         avatar.setAvatarId(avatarId);\r
311 \r
312         return avatar;\r
313     }\r
314 \r
315     /**\r
316      * AvatarフルネームからAvatarを得る。\r
317      * まだこの村にいないAvatarならAvatar一覧に登録される。\r
318      * @param seq Avatarフルネーム\r
319      * @return Avatarモデル\r
320      */\r
321     public AvatarData getAvatarData(CharSequence seq){\r
322         for(AvatarData avatar : this.avatarList){\r
323             String avfullName = avatar.getFullName();\r
324             if(avfullName.contentEquals(seq)){\r
325                 return avatar;\r
326             }\r
327         }\r
328 \r
329         PreDefAvatar predefAvatar =\r
330                 AvatarData.getPreDefAvatar(seq);\r
331         if(predefAvatar != null){\r
332             AvatarData avatar = new AvatarData(predefAvatar);\r
333             this.avatarList.add(avatar);\r
334             return avatar;\r
335         }\r
336 \r
337         AvatarData avatar = createAvatar(seq.toString());\r
338         this.avatarList.add(avatar);\r
339 \r
340         return avatar;\r
341     }\r
342 \r
343     /**\r
344      * avatarList要素のXML出力。\r
345      * @param writer 出力先\r
346      * @throws IOException 出力エラー\r
347      */\r
348     public void dumpAvatarList(Writer writer) throws IOException{\r
349         writer.append("<avatarList>").append("\n\n");\r
350 \r
351         for(AvatarData avatar : this.avatarList){\r
352             avatar.dumpXml(writer);\r
353             writer.append('\n');\r
354         }\r
355 \r
356         writer.append("</avatarList>").append('\n');\r
357 \r
358         return;\r
359     }\r
360 \r
361     /**\r
362      * 全period要素のXML出力。\r
363      * @param writer 出力先\r
364      * @throws IOException 出力エラー\r
365      */\r
366     public void dumpPeriodList(Writer writer) throws IOException{\r
367         for(PeriodData period : this.periodList){\r
368             period.dumpXml(writer);\r
369             writer.append('\n');\r
370         }\r
371         return;\r
372     }\r
373 \r
374     /**\r
375      * village要素のXML出力。\r
376      * @param writer 出力先\r
377      * @throws IOException 出力エラー\r
378      */\r
379     public void dumpXml(Writer writer) throws IOException{\r
380         writer.append("<village\n");\r
381 \r
382         XmlUtils.indent(writer, 1);\r
383         XmlUtils.dumpNameSpaceDecl(writer);\r
384         writer.append('\n');\r
385 \r
386         XmlUtils.indent(writer, 1);\r
387         XmlUtils.dumpSiNameSpaceDecl(writer);\r
388         writer.append('\n');\r
389 \r
390         XmlUtils.indent(writer, 1);\r
391         XmlUtils.dumpSchemeLocation(writer);\r
392         writer.append('\n');\r
393 \r
394         XmlUtils.indent(writer, 1);\r
395         XmlUtils.attrOut(writer, "xml:lang", "ja-JP");\r
396         writer.append('\n');\r
397 \r
398         XmlUtils.indent(writer, 1);\r
399         XmlUtils.attrOut(writer, "xml:base", this.baseUri);\r
400         writer.append('\n');\r
401 \r
402         XmlUtils.indent(writer, 1);\r
403         XmlUtils.attrOut(writer, "fullName", this.fullName);\r
404 \r
405         writer.append(' ');\r
406         XmlUtils.attrOut(writer, "vid", Integer.toString(this.villageId));\r
407         writer.append('\n');\r
408 \r
409         XmlUtils.indent(writer, 1);\r
410         XmlUtils.timeAttrOut(writer,\r
411                              "commitTime",\r
412                              this.commitHour, this.commitMinute);\r
413         writer.append('\n');\r
414 \r
415         XmlUtils.indent(writer, 1);\r
416         XmlUtils.attrOut(writer, "state", "gameover");\r
417 \r
418         DisclosureType type = getDisclosureType();\r
419         if(type != DisclosureType.COMPLETE){\r
420             writer.append(' ');\r
421             XmlUtils.attrOut(writer, "disclosure", type.getXmlName());\r
422         }\r
423 \r
424         String isValid;\r
425         if(this.landDef.isValidVillageId(this.villageId)){\r
426             isValid = "true";\r
427         }else{\r
428             isValid = "false";\r
429         }\r
430         writer.append(' ');\r
431         XmlUtils.attrOut(writer, "isValid", isValid);\r
432         writer.append('\n');\r
433 \r
434         XmlUtils.indent(writer, 1);\r
435         XmlUtils.attrOut(writer, "landName", this.landDef.getLandName());\r
436 \r
437         writer.append(' ');\r
438         XmlUtils.attrOut(writer, "formalName", this.landDef.getFormalName());\r
439         writer.append('\n');\r
440 \r
441         XmlUtils.indent(writer, 1);\r
442         XmlUtils.attrOut(writer, "landId", this.landDef.getLandId());\r
443 \r
444         writer.append(' ');\r
445         XmlUtils.attrOut(writer, "landPrefix", this.landDef.getLandPrefix());\r
446         writer.append('\n');\r
447 \r
448         XmlUtils.indent(writer, 1);\r
449         String locale = this.landDef.getLocale().toString();\r
450         locale = locale.replaceAll("_", "-");\r
451         XmlUtils.attrOut(writer, "locale", locale);\r
452 \r
453         writer.append(' ');\r
454         XmlUtils.attrOut(writer,\r
455                 "origencoding", this.landDef.getEncoding().name());\r
456 \r
457         writer.append(' ');\r
458         XmlUtils.attrOut(writer,\r
459                 "timezone", this.landDef.getTimeZone().getID());\r
460         writer.append('\n');\r
461 \r
462         XmlUtils.indent(writer, 1);\r
463         XmlUtils.attrOut(writer, "graveIconURI", getGraveIconUri());\r
464         writer.append('\n');\r
465 \r
466         XmlUtils.indent(writer, 1);\r
467         XmlUtils.attrOut(writer, "generator", JinArchiver.GENERATOR);\r
468         writer.append('\n');\r
469 \r
470         writer.append(">").append('\n');\r
471 \r
472         writer.append('\n');\r
473         dumpAvatarList(writer);\r
474 \r
475         writer.append('\n');\r
476         dumpPeriodList(writer);\r
477 \r
478         writer.append("</village>").append("\n");\r
479 \r
480         return;\r
481     }\r
482 \r
483 }\r