1 package charactermanaj.model.io;
\r
3 import java.awt.image.BufferedImage;
\r
4 import java.io.BufferedInputStream;
\r
5 import java.io.BufferedOutputStream;
\r
7 import java.io.FileOutputStream;
\r
8 import java.io.IOException;
\r
9 import java.io.InputStream;
\r
10 import java.io.OutputStream;
\r
11 import java.net.URI;
\r
12 import java.util.Collection;
\r
13 import java.util.logging.Level;
\r
14 import java.util.logging.Logger;
\r
16 import charactermanaj.model.AppConfig;
\r
17 import charactermanaj.model.CharacterData;
\r
18 import charactermanaj.model.PartsAuthorInfo;
\r
19 import charactermanaj.model.PartsCategory;
\r
20 import charactermanaj.model.PartsManageData;
\r
21 import charactermanaj.model.io.AbstractCharacterDataArchiveFile.CategoryLayerPair;
\r
22 import charactermanaj.model.io.AbstractCharacterDataArchiveFile.PartsImageContent;
\r
23 import charactermanaj.ui.progress.ProgressHandle;
\r
25 public class ImportModel {
\r
30 private static final Logger logger = Logger.getLogger(ImportModel.class.getName());
\r
35 private URI importSource;
\r
38 * プロファイル先のキャラクター定義、新規の場合はnull
\r
40 private CharacterData currentCharacterData;
\r
44 * インポートもとアーカイブ. ロードされた場合に非nullとなる.
\r
46 private CharacterDataArchiveFile archiveFile;
\r
50 * インポートされたキャラクター定義、なければnull
\r
52 private CharacterData sourceCharacterData;
\r
55 * インポートされたサンプルピクチャ、なければnull
\r
57 private BufferedImage samplePicture;
\r
62 private String readme;
\r
65 * インポート先のキャラクター定義、もしくは現在のキャラクター定義のディレクトリ構成から 読み取ることのできるパーツのコレクション、なければ空.<br>
\r
67 private Collection<PartsImageContent> partsImageContentsMap;
\r
72 private PartsManageData partsManageData;
\r
75 public void openImportSource(URI importSource, CharacterData currentCharacterData) throws IOException {
\r
76 if (archiveFile != null || importSource == null) {
\r
77 throw new IllegalStateException("既にアーカイブがオープンされています。");
\r
79 this.importSource = importSource;
\r
80 this.currentCharacterData = currentCharacterData;
\r
83 public void closeImportSource() throws IOException {
\r
84 if (archiveFile != null) {
\r
86 archiveFile.close();
\r
88 // クローズに失敗しても閉じたことにする.
\r
94 public void loadContents(ProgressHandle progressHandle) throws IOException {
\r
95 if (archiveFile != null) {
\r
96 throw new IllegalStateException("既にアーカイブがオープンされています。");
\r
98 if (importSource == null) {
\r
99 throw new IllegalStateException("インポートファィルが指定されていません。");
\r
102 CharacterDataFileReaderWriterFactory factory = CharacterDataFileReaderWriterFactory.getInstance();
\r
104 progressHandle.setCaption("open archive...");
\r
105 archiveFile = factory.openArchive(importSource);
\r
107 readme = archiveFile.readReadMe();
\r
109 progressHandle.setCaption("search the character definition...");
\r
110 sourceCharacterData = archiveFile.readCharacterData();
\r
111 if (sourceCharacterData == null) {
\r
112 // character.xmlがない場合は、character.iniで試行する.
\r
114 sourceCharacterData = archiveFile.readCharacterINI();
\r
115 if (sourceCharacterData != null) {
\r
116 // readmeがあれば、それを説明として登録しておく
\r
117 if (readme != null && readme.trim().length() > 0) {
\r
118 sourceCharacterData.setDescription(readme);
\r
123 // character.xmlがあった場合、favorites.xmlもあれば読み込む.
\r
124 archiveFile.readFavorites(sourceCharacterData);
\r
127 // サンプルピクチャの読み込み、なければnull
\r
128 progressHandle.setCaption("load sample picture...");
\r
129 samplePicture = archiveFile.readSamplePicture();
\r
131 // パーツセットの読み込み、なければ空
\r
132 progressHandle.setCaption("load partssets...");
\r
133 if (currentCharacterData != null) {
\r
134 // 既存のキャラクターセットの定義をもとにパーツディレクトリを探索する場合
\r
135 // (インポートもと・インポート先が同一であればパーツは除外される.)
\r
136 partsImageContentsMap = archiveFile.getPartsImageContents(currentCharacterData, false);
\r
138 // インポート元にあるキャラクター定義をもとにパーツディレクトリを探索する場合
\r
139 partsImageContentsMap = archiveFile.getPartsImageContents(sourceCharacterData, true);
\r
143 progressHandle.setCaption("load parts definitions...");
\r
144 partsManageData = archiveFile.getPartsManageData();
\r
147 protected void reset() {
\r
148 importSource = null;
\r
149 archiveFile = null;
\r
150 sourceCharacterData = null;
\r
151 samplePicture = null;
\r
153 partsImageContentsMap = null;
\r
154 partsManageData = null;
\r
159 public URI getImportSource() {
\r
160 return importSource;
\r
163 protected void checkArchiveOpened() {
\r
164 if (archiveFile == null) {
\r
165 throw new IllegalStateException("アーカイブはオープンされていません。");
\r
169 public CharacterData getCharacterData() {
\r
170 checkArchiveOpened();
\r
171 return sourceCharacterData;
\r
174 public BufferedImage getSamplePicture() {
\r
175 checkArchiveOpened();
\r
176 return samplePicture;
\r
179 public String getReadme() {
\r
180 checkArchiveOpened();
\r
184 public Collection<PartsImageContent> getPartsImageContents() {
\r
185 checkArchiveOpened();
\r
186 return partsImageContentsMap;
\r
189 public PartsManageData getPartsManageData() {
\r
190 checkArchiveOpened();
\r
191 return partsManageData;
\r
197 * パーツデータをプロファイルの画像ディレクトリに一括コピーする.<br>
\r
199 * @param partsImageContents
\r
203 * @throws IOException
\r
206 public void copyPartsImageContents(
\r
207 Collection<PartsImageContent> partsImageContents, CharacterData cd)
\r
208 throws IOException {
\r
209 if (cd == null || cd.getDocBase() == null) {
\r
210 throw new IllegalArgumentException("invalid character data");
\r
214 URI docbase = cd.getDocBase();
\r
215 if ( !"file".equals(docbase.getScheme())) {
\r
216 throw new IOException("ファイル以外はサポートしていません: " + docbase);
\r
218 File configFile = new File(docbase);
\r
219 File baseDir = configFile.getParentFile();
\r
220 if (baseDir == null || !baseDir.isDirectory()) {
\r
221 throw new IOException("親フォルダがディレクトリではありません: " + baseDir);
\r
224 AppConfig appConfig = AppConfig.getInstance();
\r
225 byte[] stmbuf = new byte[appConfig.getFileTransferBufferSize()];
\r
228 for (PartsImageContent content : partsImageContents) {
\r
229 InputStream is = new BufferedInputStream(content.openStream());
\r
231 File outDir = new File(baseDir, content.getDirName());
\r
232 if (!outDir.exists()) {
\r
233 if (!outDir.mkdirs()) {
\r
234 logger.log(Level.WARNING, "can't create the directory. " + outDir);
\r
237 File outFile = new File(outDir, content.getFileName());
\r
238 OutputStream os = new BufferedOutputStream(new FileOutputStream(outFile));
\r
241 int rd = is.read(stmbuf);
\r
245 os.write(stmbuf, 0, rd);
\r
251 if (!outFile.setLastModified(content.lastModified())) {
\r
252 logger.log(Level.WARNING, "can't change the modified-date: " + outFile);
\r
262 * パーツ管理情報を更新または作成する.<br>
\r
263 * パーツ管理情報がnullまたは空であれば何もしない.<br>
\r
264 * そうでなければインポートするパーツに該当するパーツ管理情報を、現在のプロファイルのパーツ管理情報に追記・更新し、 それを書き出す.<br>
\r
265 * インポートもとにパーツ管理情報がなく、既存にある場合、インポートしても管理情報は削除されません.(上書きセマンティクスのため)
\r
267 * @param partsImageContents
\r
269 * @param partsManageData
\r
272 * 現在のパーツ管理データを保持しているプロファイル、新規の場合はnull
\r
275 * @throws IOException
\r
278 public void updatePartsManageData(
\r
279 Collection<PartsImageContent> partsImageContents,
\r
280 PartsManageData partsManageData, CharacterData current,
\r
281 CharacterData target) throws IOException {
\r
282 if (target == null || !target.isValid()) {
\r
283 throw new IllegalArgumentException();
\r
286 if (partsImageContents == null || partsImageContents.isEmpty()
\r
287 || partsManageData == null || partsManageData.isEmpty()) {
\r
288 // インポートするパーツが存在しないか、管理情報がない場合は更新しようがないので何もしないで戻る.
\r
292 PartsInfoXMLReader xmlReader = new PartsInfoXMLReader();
\r
294 PartsManageData mergedPartsManagedData;
\r
295 if (current != null && current.isValid()) {
\r
296 // 現在のプロファイルからパーツ管理情報を取得する.
\r
297 mergedPartsManagedData = xmlReader.loadPartsManageData(current.getDocBase());
\r
300 mergedPartsManagedData = new PartsManageData();
\r
303 // インポート対象のパーツに該当するパーツ管理情報のみを取り出して追記する.
\r
304 for (PartsImageContent partsImageContent : partsImageContents) {
\r
305 String partsName = partsImageContent.getPartsName();
\r
306 for (CategoryLayerPair catLayerPair : partsImageContent.getCategoryLayerPairs()) {
\r
307 PartsCategory partsCategory = catLayerPair.getPartsCategory();
\r
308 String categoryId = partsCategory.getCategoryId();
\r
310 PartsManageData.PartsKey partsKey = new PartsManageData.PartsKey(partsName, categoryId);
\r
312 PartsAuthorInfo partsAuthorInfo = partsManageData.getPartsAuthorInfo(partsKey);
\r
313 PartsManageData.PartsVersionInfo versionInfo = partsManageData.getVersion(partsKey);
\r
314 String localizedName = partsManageData.getLocalizedName(partsKey);
\r
316 if (partsAuthorInfo != null || versionInfo != null || localizedName != null) {
\r
317 // いずれかの情報の登録がある場合、パーツ管理情報として追記する.
\r
318 mergedPartsManagedData.putPartsInfo(partsKey, localizedName, partsAuthorInfo, versionInfo);
\r
324 PartsInfoXMLWriter partsInfoXMLWriter = new PartsInfoXMLWriter();
\r
325 partsInfoXMLWriter.savePartsManageData(target.getDocBase(),
\r
326 mergedPartsManagedData);
\r