001/* 002 * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games. 003 * Copyright (C) 2000-2010 The Gridarta Developers. 004 * 005 * This program is free software; you can redistribute it and/or modify 006 * it under the terms of the GNU General Public License as published by 007 * the Free Software Foundation; either version 2 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License along 016 * with this program; if not, write to the Free Software Foundation, Inc., 017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 018 */ 019 020package net.sf.gridarta.model.resource; 021 022import java.io.BufferedWriter; 023import java.io.File; 024import java.io.FileOutputStream; 025import java.io.IOException; 026import java.io.OutputStream; 027import java.io.OutputStreamWriter; 028import java.io.Writer; 029import java.util.ArrayList; 030import java.util.Collections; 031import java.util.Enumeration; 032import java.util.HashMap; 033import java.util.List; 034import java.util.Map; 035import java.util.ResourceBundle; 036import java.util.regex.Pattern; 037import net.sf.gridarta.model.anim.AnimationObject; 038import net.sf.gridarta.model.anim.AnimationObjects; 039import net.sf.gridarta.model.anim.TestAnimationObjects; 040import net.sf.gridarta.model.archetype.ArchetypeFactory; 041import net.sf.gridarta.model.archetype.TestArchetype; 042import net.sf.gridarta.model.archetype.TestArchetypeBuilder; 043import net.sf.gridarta.model.archetype.TestArchetypeFactory; 044import net.sf.gridarta.model.archetypeset.ArchetypeSet; 045import net.sf.gridarta.model.archetypeset.DefaultArchetypeSet; 046import net.sf.gridarta.model.errorview.ErrorView; 047import net.sf.gridarta.model.errorview.TestErrorView; 048import net.sf.gridarta.model.face.ArchFaceProvider; 049import net.sf.gridarta.model.face.FaceObjectProviders; 050import net.sf.gridarta.model.face.FaceObjects; 051import net.sf.gridarta.model.face.TestFaceObjects; 052import net.sf.gridarta.model.gameobject.GameObjectFactory; 053import net.sf.gridarta.model.gameobject.TestGameObject; 054import net.sf.gridarta.model.gameobject.TestGameObjectFactory; 055import net.sf.gridarta.model.io.AbstractArchetypeParser; 056import net.sf.gridarta.model.io.TestArchetypeParser; 057import net.sf.gridarta.model.maparchobject.TestMapArchObject; 058import net.sf.gridarta.utils.ResourceIcons; 059import net.sf.japi.swing.action.ActionBuilder; 060import net.sf.japi.swing.action.ActionBuilderFactory; 061import net.sf.japi.swing.action.DefaultActionBuilder; 062import net.sf.japi.util.IteratorEnumeration; 063import org.jetbrains.annotations.NotNull; 064import org.jetbrains.annotations.Nullable; 065import org.junit.Assert; 066import org.junit.Test; 067 068/** 069 * Regression tests for {@link AbstractFilesResourcesReader}. 070 * @author Andreas Kirschbaum 071 */ 072public class AbstractFilesResourcesReaderTest { 073 074 /** 075 * The {@link Pattern} for matching validator keys for default values. 076 */ 077 @NotNull 078 private static final Pattern PATTERN_DEFAULT_KEY = Pattern.compile("fileDialog\\.filter\\..*"); 079 080 /** 081 * checks that animations read from .anim files have correct path names. 082 * @throws IOException if the test fails 083 */ 084 @Test 085 public void testAnimationPaths() throws IOException { 086 final File tmpDirectory = File.createTempFile("gridarta", null); 087 try { 088 Assert.assertTrue(tmpDirectory.delete()); 089 Assert.assertTrue(tmpDirectory.mkdir()); 090 final File archDirectory = new File(tmpDirectory, "archetypes"); 091 Assert.assertTrue(archDirectory.mkdir()); 092 final File collectedDirectory = new File(tmpDirectory, "collected"); 093 Assert.assertTrue(collectedDirectory.mkdir()); 094 createAnimationFile(archDirectory, "anim1"); 095 createAnimationFile(new File(archDirectory, "p"), "anim2"); 096 createAnimationFile(new File(new File(new File(archDirectory, "p"), "q"), "r"), "anim3"); 097 098 final ActionBuilder actionBuilder = new DefaultActionBuilder("net.sf.gridarta"); 099 ActionBuilderFactory.getInstance().putActionBuilder("net.sf.gridarta", actionBuilder); 100 final ResourceBundle resourceBundle = new ResourceBundle() { 101 102 /** 103 * Maps key to associated object. 104 */ 105 @NotNull 106 private final Map<String, Object> objects = new HashMap<String, Object>(); 107 108 @Nullable 109 @Override 110 protected Object handleGetObject(@NotNull final String key) { 111 final Object existingObject = objects.get(key); 112 if (existingObject != null) { 113 return existingObject; 114 } 115 116 final Object object; 117 if (PATTERN_DEFAULT_KEY.matcher(key).matches()) { 118 object = "Description"; 119 } else { 120 return null; 121 } 122 objects.put(key, object); 123 return object; 124 } 125 126 @NotNull 127 @Override 128 public Enumeration<String> getKeys() { 129 return new IteratorEnumeration<String>(Collections.unmodifiableSet(objects.keySet()).iterator()); 130 } 131 132 }; 133 actionBuilder.addBundle(resourceBundle); 134 135 final AnimationObjects animationObjects = readAnimations(archDirectory, collectedDirectory); 136 137 Assert.assertEquals(3, animationObjects.size()); 138 final AnimationObject anim1 = animationObjects.get("anim1"); 139 final AnimationObject anim2 = animationObjects.get("anim2"); 140 final AnimationObject anim3 = animationObjects.get("anim3"); 141 Assert.assertNotNull(anim1); 142 Assert.assertNotNull(anim2); 143 Assert.assertNotNull(anim3); 144 Assert.assertEquals("anim1", anim1.getAnimName()); 145 Assert.assertEquals("anim2", anim2.getAnimName()); 146 Assert.assertEquals("anim3", anim3.getAnimName()); 147 Assert.assertEquals("/anim1", anim1.getPath()); 148 Assert.assertEquals("/p/anim2", anim2.getPath()); 149 Assert.assertEquals("/p/q/r/anim3", anim3.getPath()); 150 } finally { 151 delete(tmpDirectory); 152 } 153 } 154 155 /** 156 * Reads resources from individual files. 157 * @param archDirectory the arch directory 158 * @param collectedDirectory the collected directory 159 * @return the animation objects instance 160 */ 161 @NotNull 162 private static AnimationObjects readAnimations(@NotNull final File archDirectory, @NotNull final File collectedDirectory) { 163 final ArchFaceProvider archFaceProvider = new ArchFaceProvider(); 164 final FaceObjects faceObjects = new TestFaceObjects(); 165 final ResourceIcons resourceIcons = new ResourceIcons(); 166 final FaceObjectProviders faceObjectProviders = new FaceObjectProviders(1, faceObjects, resourceIcons); 167 final AnimationObjects animationObjects = new TestAnimationObjects(); 168 final ArchetypeFactory<TestGameObject, TestMapArchObject, TestArchetype> archetypeFactory = new TestArchetypeFactory(faceObjectProviders, animationObjects); 169 final ArchetypeSet<TestGameObject, TestMapArchObject, TestArchetype> archetypeSet = new DefaultArchetypeSet<TestGameObject, TestMapArchObject, TestArchetype>(archetypeFactory, null); 170 final GameObjectFactory<TestGameObject, TestMapArchObject, TestArchetype> gameObjectFactory = new TestGameObjectFactory(faceObjectProviders, animationObjects); 171 final TestArchetypeBuilder archetypeBuilder = new TestArchetypeBuilder(gameObjectFactory); 172 final AbstractArchetypeParser<TestGameObject, TestMapArchObject, TestArchetype, ?> archetypeParser = new TestArchetypeParser(archetypeBuilder, animationObjects, archetypeSet); 173 final AbstractResourcesReader<TestGameObject> filesResourcesReader = new TestFilesResourcesReader(archDirectory, archetypeSet, archetypeParser, archFaceProvider, collectedDirectory, null, animationObjects, faceObjects); 174 final List<TestGameObject> invObjects = new ArrayList<TestGameObject>(); 175 final ErrorView errorView = new TestErrorView(); 176 filesResourcesReader.read(errorView, invObjects); 177 return animationObjects; 178 } 179 180 /** 181 * Creates a new .anim file. 182 * @param directory the directory to create the file in; will be created if 183 * it does not yet exist 184 * @param animName the name of the animation 185 * @throws IOException if an I/O error occurs 186 */ 187 private static void createAnimationFile(@NotNull final File directory, @NotNull final String animName) throws IOException { 188 if (!directory.isDirectory()) { 189 Assert.assertTrue(directory.mkdirs()); 190 } 191 192 final File file = new File(directory, animName + ".anim"); 193 Assert.assertFalse(file.exists()); 194 final OutputStream fileOutputStream = new FileOutputStream(file); 195 try { 196 final Writer outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8"); 197 try { 198 final Writer bufferedWriter = new BufferedWriter(outputStreamWriter); 199 try { 200 bufferedWriter.append("anim ").append(animName).append("\n"); 201 bufferedWriter.append("face1\n"); 202 bufferedWriter.append("face2\n"); 203 bufferedWriter.append("mina\n"); 204 } finally { 205 bufferedWriter.close(); 206 } 207 } finally { 208 outputStreamWriter.close(); 209 } 210 } finally { 211 fileOutputStream.close(); 212 } 213 } 214 215 /** 216 * Recursively deletes a directory. 217 * @param file the file or directory to delete 218 */ 219 private static void delete(@NotNull final File file) { 220 //noinspection ResultOfMethodCallIgnored 221 file.delete(); 222 223 if (file.isDirectory()) { 224 final File[] files = file.listFiles(); 225 if (files != null) { 226 for (final File subFile : files) { 227 delete(subFile); 228 } 229 } 230 } 231 232 if (file.exists()) { 233 Assert.assertTrue(file.delete()); 234 } 235 } 236 237}