OSDN Git Service

961fb342967c2e3e97ccb4fd053c074353b4dbfd
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / model / io / WorkingSetPersist.java
1 package charactermanaj.model.io;
2
3 import java.io.BufferedInputStream;
4 import java.io.File;
5 import java.io.FileFilter;
6 import java.io.FileInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.OutputStream;
10 import java.net.URI;
11 import java.util.Map;
12 import java.util.logging.Level;
13 import java.util.logging.Logger;
14
15 import charactermanaj.model.CharacterData;
16 import charactermanaj.model.IndependentPartsSetInfo;
17 import charactermanaj.model.IndependentWorkingSet;
18 import charactermanaj.model.PartsColorInfo;
19 import charactermanaj.model.PartsIdentifier;
20 import charactermanaj.model.PartsSet;
21 import charactermanaj.model.WorkingSet;
22 import charactermanaj.util.FileUtilities;
23 import charactermanaj.util.UserData;
24 import charactermanaj.util.UserDataFactory;
25
26 /**
27  * ワーキングセットの保存と復元.<br>
28  *
29  * @author seraphy
30  */
31 public class WorkingSetPersist {
32
33         /**
34          * ロガー
35          */
36         private static final Logger logger = Logger
37                         .getLogger(WorkingSetPersist.class.getName());
38
39         /**
40          * ワーキングセットのサフィックス.
41          */
42         private static final String WORKINGSET_FILE_SUFFIX = "workingset.xml";
43
44         private static final WorkingSetPersist singletion = new WorkingSetPersist();
45
46         private final UserDataFactory userDataFactory = UserDataFactory.getLocalInstance();
47
48         public static WorkingSetPersist getInstance() {
49                 return singletion;
50         }
51
52         /**
53          * すべてのワーキングセットをクリアする.<br>
54          */
55         public void removeAllWorkingSet() {
56                 File dir = userDataFactory.getSpecialDataDir("foo-" + WORKINGSET_FILE_SUFFIX);
57                 if (dir.exists() && dir.isDirectory()) {
58                         File[] files = dir.listFiles(new FileFilter() {
59                                 public boolean accept(File pathname) {
60                                         return pathname.isFile() && pathname.getName().endsWith(WORKINGSET_FILE_SUFFIX);
61                                 }
62                         });
63                         if (files == null) {
64                                 logger.log(Level.WARNING, "dir access failed. " + dir);
65                                 return;
66                         }
67                         for (File file : files) {
68                                 logger.log(Level.INFO, "remove file: " + file);
69                                 try {
70                                         FileUtilities.delete(file);
71                                 } catch (Exception ex) {
72                                         logger.log(Level.WARNING, "failed to remove file: " + file, ex);
73                                 }
74                         }
75                 }
76         }
77
78         /**
79          * ワーキングセットを削除する.
80          *
81          * @param cd
82          *            対象のキャラクターデータ
83          */
84         public void removeWorkingSet(CharacterData cd) {
85                 UserData workingSetXmlData = userDataFactory.getMangledNamedUserData(
86                                 cd.getDocBase(), WORKINGSET_FILE_SUFFIX);
87                 if (workingSetXmlData != null && workingSetXmlData.exists()) {
88                         logger.log(Level.INFO, "remove file: " + workingSetXmlData);
89                         workingSetXmlData.delete();
90                 }
91         }
92
93         /**
94          * ワーキングセットを保存する.<br>
95          * ワーキングセットインスタンスには、あらかじめ全て設定しておく必要がある.<br>
96          *
97          * @param workingSet
98          *            ワーキングセット
99          * @throws IOException
100          *             失敗
101          */
102         public void saveWorkingSet(WorkingSet workingSet) throws IOException {
103                 if (workingSet == null) {
104                         throw new IllegalArgumentException();
105                 }
106                 CharacterData characterData = workingSet.getCharacterData();
107                 if (characterData == null) {
108                         throw new IllegalArgumentException("character-data must be set.");
109                 }
110
111                 // XML形式でのワーキングセットの保存
112                 UserData workingSetXmlData = userDataFactory.getMangledNamedUserData(
113                                 characterData.getDocBase(), WORKINGSET_FILE_SUFFIX);
114                 OutputStream outstm = workingSetXmlData.getOutputStream();
115                 try {
116                         WorkingSetXMLWriter workingSetXmlWriter = new WorkingSetXMLWriter();
117                         workingSetXmlWriter.writeWorkingSet(workingSet, outstm);
118                 } finally {
119                         outstm.close();
120                 }
121         }
122
123         /**
124          * ワーキングセットを取得する.<br>
125          *
126          * @param characterData
127          *            対象のキャラクターデータ
128          * @return ワーキングセット、なければnull
129          * @throws IOException
130          *             読み込みに失敗した場合
131          */
132         public WorkingSet loadWorkingSet(CharacterData characterData)
133                         throws IOException {
134                 if (characterData == null) {
135                         throw new IllegalArgumentException();
136                 }
137                 // XML形式でのワーキングセットの復元
138                 UserData workingSetXmlData = userDataFactory.getMangledNamedUserData(
139                                 characterData.getDocBase(), WORKINGSET_FILE_SUFFIX);
140                 if (workingSetXmlData == null || !workingSetXmlData.exists()) {
141                         // 保存されていない場合
142                         return null;
143                 }
144
145                 // キャラクターデータと関連づけられていないワーキングセットデータを取得する
146                 IndependentWorkingSet workingSet2;
147
148                 InputStream is = workingSetXmlData.openStream();
149                 try {
150                         WorkingSetXMLReader WorkingSetXMLReader = new WorkingSetXMLReader();
151                         workingSet2 = WorkingSetXMLReader.loadWorkingSet(is);
152
153                 } finally {
154                         is.close();
155                 }
156
157                 // 現在のキャラクターデータと照合する。
158                 URI docBase = characterData.getDocBase();
159                 if (docBase != null
160                                 && !docBase.equals(workingSet2.getCharacterDocBase())) {
161                         // docBaseが一致せず
162                         logger.log(Level.INFO, "docBase missmatch");
163                         return null;
164                 }
165                 String sig = characterData.toSignatureString();
166                 if (!sig.equals(workingSet2.getCharacterDataSig())) {
167                         // 構造が一致せず.
168                         logger.log(Level.INFO, "character data structure missmatch");
169                         return null;
170                 }
171
172                 // 現在のキャラクターデータに関連づけられているワーキングセットとして転記する
173
174                 WorkingSet ws = new WorkingSet();
175                 ws.setCharacterData(characterData);
176                 ws.setCharacterDataRev(characterData.getRev());
177                 ws.setCharacterDocBase(docBase);
178
179                 ws.setLastUsedExportDir(workingSet2.getLastUsedExportDir());
180                 ws.setLastUsedSaveDir(workingSet2.getLastUsedSaveDir());
181
182                 // パーツの色情報を復元する.
183                 Map<PartsIdentifier, PartsColorInfo> partsColorInfoMap = characterData
184                                 .getPartsColorManager().getPartsColorInfoMap();
185                 workingSet2.createCompatible(characterData, partsColorInfoMap);
186                 ws.setPartsColorInfoMap(partsColorInfoMap);
187
188                 // 選択されているパーツの復元
189                 IndependentPartsSetInfo partsSetInfo = workingSet2.getCurrentPartsSet();
190                 if (partsSetInfo != null) {
191                         PartsSet partsSet = IndependentPartsSetInfo.convertPartsSet(
192                                         partsSetInfo, characterData, false);
193                         ws.setCurrentPartsSet(partsSet);
194
195                         // 最後に選択したお気に入り情報の復元
196                         IndependentPartsSetInfo lastUsePresetPartsInfo = workingSet2
197                                         .getLastUsePresetParts();
198                         if (lastUsePresetPartsInfo != null
199                                         && lastUsePresetPartsInfo.getId() != null
200                                         && lastUsePresetPartsInfo.getId().trim().length() > 0) {
201                                 PartsSet lastUsePresetParts = IndependentPartsSetInfo
202                                                 .convertPartsSet(lastUsePresetPartsInfo,
203                                                                 characterData, false);
204                                 ws.setLastUsePresetParts(lastUsePresetParts);
205                         }
206                 }
207
208                 ws.setWallpaperInfo(workingSet2.getWallpaperInfo());
209
210                 ws.setViewPosition(workingSet2.getViewPosition());
211                 ws.setWindowRect(workingSet2.getWindowRect());
212
213                 return ws;
214         }
215
216         /**
217          * 古いワーキングセットについて、すでに本体データが削除されている場合はワーキングセットも削除する。
218          * まだ存在するものは削除されない。
219          * 生きている場合は、ワーキングセットの検査日時を表すために更新日時を現在日時に設定しなおす。
220          * @param expireDate 判定対象となる日時、それ以前のもののみ判定を行う。
221          */
222         public void purge(final long expireDate) {
223                 final String XML_SUFFIX = "-" + WORKINGSET_FILE_SUFFIX;
224
225                 UserDataFactory userDataFactory = UserDataFactory.getLocalInstance();
226                 File dir = userDataFactory.getSpecialDataDir(XML_SUFFIX);
227
228                 File[] xmls = dir.listFiles(new FileFilter() {
229                         @Override
230                         public boolean accept(File pathname) {
231                                 return pathname.isFile() && pathname.getName().endsWith(XML_SUFFIX)
232                                                 && pathname.lastModified() < expireDate && pathname.length() > 0;
233                         }
234                 });
235                 if (xmls == null) {
236                         logger.log(Level.WARNING, "workingset-dir access failed.");
237                         return;
238                 }
239
240                 for (File xmlFile : xmls) {
241                         try {
242                                 WorkingSetXMLReader reader = new WorkingSetXMLReader();
243                                 IndependentWorkingSet ws;
244                                 InputStream is = new BufferedInputStream(new FileInputStream(xmlFile));
245                                 try {
246                                         ws = reader.loadWorkingSet(is);
247                                 } finally {
248                                         is.close();
249                                 }
250
251                                 URI docBase = ws.getCharacterDocBase();
252                                 if (docBase.getScheme().equals("file")) {
253                                         File characterXml = new File(docBase);
254                                         if (!characterXml.exists()) {
255                                                 // キャラクター定義XMLが存在しない = 削除されたキャラクターデータ
256                                                 logger.log(Level.INFO, "remove amandone workingset: " + xmlFile + ", docBase=" + docBase);
257                                                 xmlFile.delete();
258                                         } else {
259                                                 // チェック済みであることを示すためにXMLの更新日時を現在時刻にする
260                                                 xmlFile.setLastModified(System.currentTimeMillis());
261                                         }
262                                 }
263
264                         } catch (Exception ex) {
265                                 logger.log(Level.WARNING, "file access failed. " + xmlFile, ex);
266                         }
267                 }
268         }
269 }