From d45a92e74867d9a30610280fd487606bb00701c3 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Tue, 13 Mar 2012 06:17:34 +0000 Subject: [PATCH] CardReader.readCard is a public static function now. This will allow to store pets' characteristics as card description txt files. --- .gitattributes | 1 + src/main/java/forge/CardReader.java | 303 ++++++++---------- .../java/forge/game/limited/CardRatings.java | 9 +- .../java/forge/game/limited/SealedDeck.java | 2 +- src/main/java/forge/model/FModel.java | 4 +- .../forge/quest/data/pet/QuestPetPlant.java | 1 + src/main/java/forge/util/FileUtil.java | 50 ++- src/main/java/forge/util/LineReader.java | 145 +++++++++ .../java/forge/util/StorageReaderFile.java | 4 +- 9 files changed, 329 insertions(+), 190 deletions(-) create mode 100644 src/main/java/forge/util/LineReader.java diff --git a/.gitattributes b/.gitattributes index 7c84b36f35c..5615d83d75c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11637,6 +11637,7 @@ src/main/java/forge/util/IItemSerializer.java -text src/main/java/forge/util/IStorage.java -text src/main/java/forge/util/IStorageView.java -text src/main/java/forge/util/IgnoringXStream.java -text +src/main/java/forge/util/LineReader.java -text src/main/java/forge/util/MyRandom.java svneol=native#text/plain src/main/java/forge/util/Predicate.java -text src/main/java/forge/util/PredicateString.java -text diff --git a/src/main/java/forge/CardReader.java b/src/main/java/forge/CardReader.java index 26ac0d99cdb..894afdab6c7 100644 --- a/src/main/java/forge/CardReader.java +++ b/src/main/java/forge/CardReader.java @@ -51,6 +51,8 @@ import forge.card.replacement.ReplacementHandler; import forge.card.trigger.TriggerHandler; import forge.error.ErrorViewer; import forge.gui.toolbox.FProgressBar; +import forge.util.FileUtil; +import forge.util.LineReader; import forge.view.SplashFrame; /** @@ -341,35 +343,6 @@ public class CardReader implements Runnable { } } - /** - *

- * Reads a line from the given reader and handles exceptions. - *

- * - * @param reader - * a {@link java.io.BufferedReader} object. - * @return a {@link java.lang.String} object. - */ - public static String readLine(final BufferedReader reader) { - // makes the checked exception, into an unchecked runtime exception - try { - String line = reader.readLine(); - if (line != null) { - line = line.trim(); - } - return line; - } catch (final Exception ex) { - ErrorViewer.showError(ex); - throw new RuntimeException("CardReader : readLine(Card) error", ex); - // by - // Braids - // on - // 8/18/11 - // 10:53 - // PM - } - } // readLine(BufferedReader) - /** *

* load a card. @@ -381,142 +354,9 @@ public class CardReader implements Runnable { * @return the card loaded from the stream */ protected final Card loadCard(final InputStream inputStream) { - final Card card = new Card(); this.rulesReader.reset(); - - InputStreamReader inputStreamReader = null; - BufferedReader reader = null; - try { - inputStreamReader = new InputStreamReader(inputStream, this.charset); - reader = new BufferedReader(inputStreamReader); - - String line = CardReader.readLine(reader); - while (!"End".equals(line)) { - this.rulesReader.parseLine(line); - if (line.isEmpty()) { - // Ignore empty lines. - } else if (line.charAt(0) == '#') { - // 8/18/11 10:59 PM - // no need to do anything, this indicates a comment line - } else if (line.startsWith("Name:")) { - final String value = line.substring(5); - // System.out.println(s); - if (this.mapToFill.containsKey(value)) { - break; // this card has already been loaded. - } else { - card.setName(value); - } - } else if (line.startsWith("ManaCost:")) { - final String value = line.substring(9); - // System.out.println(s); - if (!"no cost".equals(value)) { - card.setManaCost(value); - } - } else if (line.startsWith("Types:")) { - CardReader.addTypes(card, line.substring("Types:".length())); - } else if (line.startsWith("Text:")) { - String value = line.substring("Text:".length()); - // if (!t.equals("no text")); - if ("no text".equals(value)) { - value = ""; - } - card.setText(value); - } else if (line.startsWith("PT:")) { - final String value = line.substring("PT:".length()); - final String[] powTough = value.split("/"); - int att; - if (powTough[0].contains("*")) { - att = 0; - } else { - att = Integer.parseInt(powTough[0]); - } - - int def; - if (powTough[1].contains("*")) { - def = 0; - } else { - def = Integer.parseInt(powTough[1]); - } - - card.setBaseAttackString(powTough[0]); - card.setBaseDefenseString(powTough[1]); - card.setBaseAttack(att); - card.setBaseDefense(def); - } else if (line.startsWith("Loyalty:")) { - final String[] splitStr = line.split(":"); - final int loyal = Integer.parseInt(splitStr[1]); - card.setBaseLoyalty(loyal); - } else if (line.startsWith("K:")) { - final String value = line.substring(2); - card.addIntrinsicKeyword(value); - } else if (line.startsWith("SVar:")) { - final String[] value = line.split(":", 3); - card.setSVar(value[1], value[2]); - } else if (line.startsWith("A:")) { - final String value = line.substring(2); - card.addIntrinsicAbility(value); - } else if (line.startsWith("T:")) { - final String value = line.substring(2); - card.addTrigger(TriggerHandler.parseTrigger(value, card, true)); - } else if (line.startsWith("S:")) { - final String value = line.substring(2); - card.addStaticAbilityString(value); - } else if (line.startsWith("R:")) { - final String value = line.substring(2); - card.addReplacementEffect(ReplacementHandler.parseReplacement(value, card)); - } else if (line.startsWith("SetInfo:")) { - final String value = line.substring("SetInfo:".length()); - card.addSet(new EditionInfo(value)); - // 8/18/11 11:08 PM - } else if (line.equals("ALTERNATE")) { - String mode; - if (card.isFlip()) { - mode = "Flipped"; - } else if (card.isDoubleFaced()) { - mode = "Transformed"; - } else { - mode = card.isTransformable(); - } - card.addAlternateState(mode); - card.setState(mode); - } else if (line.startsWith("AlternateMode:")) { - final String value = line.substring("AlternateMode:".length()); - if (value.equalsIgnoreCase("Flip")) { - card.setFlip(true); - } else if (value.equalsIgnoreCase("DoubleFaced")) { - card.setDoubleFaced(true); - } else { - card.setTransformable(value); - } - } else if (line.startsWith("Colors:")) { - final String value = line.substring("Colors:".length()); - final ArrayList newCols = new ArrayList(); - for (final String col : value.split(",")) { - final CardColor newCol = new CardColor(card); - newCol.addToCardColor(col); - newCols.add(newCol); - } - - card.setColor(newCols); - card.setCardColorsOverridden(true); - } - - line = CardReader.readLine(reader); - } // while !End - } finally { - try { - reader.close(); - } catch (final IOException ignored) { - // 11:08 - // PM - } - try { - inputStreamReader.close(); - } catch (final IOException ignored) { - // 11:08 - // PM - } - } + + Card card = readCard( new LineReader(inputStream, this.charset), this.rulesReader, mapToFill ); if (card.isInAlternateState()) { card.setState("Original"); @@ -526,6 +366,141 @@ public class CardReader implements Runnable { this.mapToFill.put(card.getName(), card); return card; } + + public static Card readCard(Iterable lines) + { + return readCard(lines, null, null); + } + + /** + * Returns the card read from input stream + * @param lines are input lines + * @param rulesReader is used to fill CardPrinted characteristics + * @param mapToFill is used to eliminate duplicates + * @return the card + */ + public static Card readCard(Iterable lines, CardRulesReader rulesReader, Map mapToFill) { + final Card card = new Card(); + boolean ignoreTheRest = false; + + for(String line : lines ) { + line = line.trim(); + + if("End".equals(line)) { ignoreTheRest = true; continue; } + if(ignoreTheRest) { continue; } // have to deplete the iterator + // otherwise the underlying class would close its stream on finalize only + + if (line.isEmpty() || line.charAt(0) == '#') + continue; + + if ( null != rulesReader ) + rulesReader.parseLine(line); + + if (line.startsWith("Name:")) { + final String value = line.substring(5); + // System.out.println(s); + if (mapToFill != null && mapToFill.containsKey(value)) { + break; // this card has already been loaded. + } else { + card.setName(value); + } + } else if (line.startsWith("ManaCost:")) { + final String value = line.substring(9); + // System.out.println(s); + if (!"no cost".equals(value)) { + card.setManaCost(value); + } + } else if (line.startsWith("Types:")) { + CardReader.addTypes(card, line.substring("Types:".length())); + } else if (line.startsWith("Text:")) { + String value = line.substring("Text:".length()); + // if (!t.equals("no text")); + if ("no text".equals(value)) { + value = ""; + } + card.setText(value); + } else if (line.startsWith("PT:")) { + final String value = line.substring("PT:".length()); + final String[] powTough = value.split("/"); + int att; + if (powTough[0].contains("*")) { + att = 0; + } else { + att = Integer.parseInt(powTough[0]); + } + + int def; + if (powTough[1].contains("*")) { + def = 0; + } else { + def = Integer.parseInt(powTough[1]); + } + + card.setBaseAttackString(powTough[0]); + card.setBaseDefenseString(powTough[1]); + card.setBaseAttack(att); + card.setBaseDefense(def); + } else if (line.startsWith("Loyalty:")) { + final String[] splitStr = line.split(":"); + final int loyal = Integer.parseInt(splitStr[1]); + card.setBaseLoyalty(loyal); + } else if (line.startsWith("K:")) { + final String value = line.substring(2); + card.addIntrinsicKeyword(value); + } else if (line.startsWith("SVar:")) { + final String[] value = line.split(":", 3); + card.setSVar(value[1], value[2]); + } else if (line.startsWith("A:")) { + final String value = line.substring(2); + card.addIntrinsicAbility(value); + } else if (line.startsWith("T:")) { + final String value = line.substring(2); + card.addTrigger(TriggerHandler.parseTrigger(value, card, true)); + } else if (line.startsWith("S:")) { + final String value = line.substring(2); + card.addStaticAbilityString(value); + } else if (line.startsWith("R:")) { + final String value = line.substring(2); + card.addReplacementEffect(ReplacementHandler.parseReplacement(value, card)); + } else if (line.startsWith("SetInfo:")) { + final String value = line.substring("SetInfo:".length()); + card.addSet(new EditionInfo(value)); + // 8/18/11 11:08 PM + } else if (line.equals("ALTERNATE")) { + String mode; + if (card.isFlip()) { + mode = "Flipped"; + } else if (card.isDoubleFaced()) { + mode = "Transformed"; + } else { + mode = card.isTransformable(); + } + card.addAlternateState(mode); + card.setState(mode); + } else if (line.startsWith("AlternateMode:")) { + final String value = line.substring("AlternateMode:".length()); + if (value.equalsIgnoreCase("Flip")) { + card.setFlip(true); + } else if (value.equalsIgnoreCase("DoubleFaced")) { + card.setDoubleFaced(true); + } else { + card.setTransformable(value); + } + } else if (line.startsWith("Colors:")) { + final String value = line.substring("Colors:".length()); + final ArrayList newCols = new ArrayList(); + for (final String col : value.split(",")) { + final CardColor newCol = new CardColor(card); + newCol.addToCardColor(col); + newCols.add(newCol); + } + + card.setColor(newCols); + card.setCardColorsOverridden(true); + } + } // while !End + return card; + } /** * Set the character encoding to use when loading cards. diff --git a/src/main/java/forge/game/limited/CardRatings.java b/src/main/java/forge/game/limited/CardRatings.java index c44e8fbe603..6606e4c7976 100644 --- a/src/main/java/forge/game/limited/CardRatings.java +++ b/src/main/java/forge/game/limited/CardRatings.java @@ -19,6 +19,7 @@ package forge.game.limited; import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; @@ -36,7 +37,7 @@ public class CardRatings { private static Map blockRatings = new TreeMap(); private static Map customRatings = new TreeMap(); - private static ArrayList tempRatings = new ArrayList(); + private static List tempRatings = new ArrayList(); /** * Instantiates a new card ratings. @@ -60,7 +61,7 @@ public class CardRatings { } private void loadFullRatings() { - final ArrayList sRatings = FileUtil.readFile("res/draft/fullRatings.dat"); + final List sRatings = FileUtil.readFile("res/draft/fullRatings.dat"); if (sRatings.size() > 1) { for (final String s : sRatings) { if (s.length() > 3) { @@ -74,7 +75,7 @@ public class CardRatings { } private void loadBlockRatings() { - final ArrayList sRatings = FileUtil.readFile("res/draft/blockRatings.dat"); + final List sRatings = FileUtil.readFile("res/draft/blockRatings.dat"); if (sRatings.size() > 1) { for (final String s : sRatings) { if (s.length() > 3) { @@ -88,7 +89,7 @@ public class CardRatings { } private void loadCustomRatings() { - final ArrayList sRatings = FileUtil.readFile("res/draft/customRatings.dat"); + final List sRatings = FileUtil.readFile("res/draft/customRatings.dat"); if (sRatings.size() > 1) { for (final String s : sRatings) { if (s.length() > 3) { diff --git a/src/main/java/forge/game/limited/SealedDeck.java b/src/main/java/forge/game/limited/SealedDeck.java index 48e66a46aca..e8921558b6a 100644 --- a/src/main/java/forge/game/limited/SealedDeck.java +++ b/src/main/java/forge/game/limited/SealedDeck.java @@ -136,7 +136,7 @@ public class SealedDeck { for (final String element : dList) { if (element.endsWith(".sealed")) { - final ArrayList dfData = FileUtil.readFile("res/sealed/" + element); + final List dfData = FileUtil.readFile("res/sealed/" + element); final CustomLimited cs = CustomLimited.parse(dfData, Singletons.getModel().getDecks().getCubes()); customs.add(cs); } diff --git a/src/main/java/forge/model/FModel.java b/src/main/java/forge/model/FModel.java index cbc93e42293..ecfba1adfb6 100644 --- a/src/main/java/forge/model/FModel.java +++ b/src/main/java/forge/model/FModel.java @@ -181,7 +181,7 @@ public enum FModel { */ public static void loadDynamicGamedata() { if (!Constant.CardTypes.LOADED[0]) { - final ArrayList typeListFile = FileUtil.readFile("res/gamedata/TypeLists.txt"); + final List typeListFile = FileUtil.readFile("res/gamedata/TypeLists.txt"); ArrayList tList = null; @@ -262,7 +262,7 @@ public enum FModel { } if (!Constant.Keywords.LOADED[0]) { - final ArrayList nskwListFile = FileUtil.readFile("res/gamedata/NonStackingKWList.txt"); + final List nskwListFile = FileUtil.readFile("res/gamedata/NonStackingKWList.txt"); Constant.Keywords.NON_STACKING_LIST[0] = new ConstantStringArrayList(); diff --git a/src/main/java/forge/quest/data/pet/QuestPetPlant.java b/src/main/java/forge/quest/data/pet/QuestPetPlant.java index a86da2be57f..5da98c06a37 100644 --- a/src/main/java/forge/quest/data/pet/QuestPetPlant.java +++ b/src/main/java/forge/quest/data/pet/QuestPetPlant.java @@ -92,6 +92,7 @@ public class QuestPetPlant extends QuestPetAbstract { petCard.setBaseDefense(4); petCard.addIntrinsicKeyword("Deathtouch"); + // A:AB$ GainLife | Cost$ T | LifeAmount$ 1 | SpellDescription$ You gain 1 life. final Cost abCost = new Cost("T", petCard.getName(), true); final SpellAbility ability = new AbilityActivated(petCard, abCost, null) { private static final long serialVersionUID = 7546242087593613719L; diff --git a/src/main/java/forge/util/FileUtil.java b/src/main/java/forge/util/FileUtil.java index fcf175da227..5f971072f36 100644 --- a/src/main/java/forge/util/FileUtil.java +++ b/src/main/java/forge/util/FileUtil.java @@ -26,6 +26,7 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.io.Reader; import java.net.Proxy; import java.net.URL; import java.util.ArrayList; @@ -116,7 +117,7 @@ public final class FileUtil { * a {@link java.lang.String} object. * @return a {@link java.util.ArrayList} object. */ - public static ArrayList readFile(final String filename) { + public static List readFile(final String filename) { return FileUtil.readFile(new File(filename)); } @@ -132,30 +133,47 @@ public final class FileUtil { * a {@link java.io.File} object. * @return a {@link java.util.ArrayList} object. */ - public static ArrayList readFile(final File file) { - final ArrayList list = new ArrayList(); - BufferedReader in; - + public static List readFile(final File file) { try { if ((file == null) || !file.exists()) { - return list; + return new ArrayList(); } - - in = new BufferedReader(new FileReader(file)); - - String line; - while ((line = in.readLine()) != null) { - list.add(line); - } - in.close(); + return readAllLines(new FileReader(file), false); } catch (final Exception ex) { ErrorViewer.showError(ex); throw new RuntimeException("FileUtil : readFile() error, " + ex); } - - return list; } // readFile() + public static List readAllLines(Reader reader){ + return readAllLines(reader, false); + } + + /** + * Reads all lines from given reader to a list of strings + * @param reader is a reader (e.g. FileReader, InputStreamReader) + * @param mayTrim defines whether to trim lines. + * @return list of strings + */ + public static List readAllLines(Reader reader, boolean mayTrim){ + final ArrayList list = new ArrayList(); + try { + BufferedReader in = new BufferedReader(reader); + String line; + while ((line = in.readLine()) != null) { + if ( mayTrim ) { + line = line.trim(); + } + list.add(line); + } + in.close(); + } catch (IOException ex ) { + ErrorViewer.showError(ex); + throw new RuntimeException("FileUtil : readAllLines() error, " + ex); + } + return list; + } + /** * Download url into file. * diff --git a/src/main/java/forge/util/LineReader.java b/src/main/java/forge/util/LineReader.java new file mode 100644 index 00000000000..f6eafa1d2e6 --- /dev/null +++ b/src/main/java/forge/util/LineReader.java @@ -0,0 +1,145 @@ +package forge.util; + +/** + * TODO: Write javadoc for this type. + * + */ +import java.io.BufferedReader; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Represents the lines found in an {@link InputStream}. The lines are read + * one at a time using {@link BufferedReader#readLine()} and may be streamed + * through an iterator or returned all at once. + * + *

This class does not handle any concurrency issues. + * + *

The stream is closed automatically when the for loop is done :) + * + *

{@code
+ * for(String line : new LineReader(stream))
+ *      // ...
+ * }
+ * + *

An {@link IllegalStateException} will be thrown if any {@link IOException}s + * occur when reading or closing the stream. + * + * @author Torleif Berger + * @license http://creativecommons.org/licenses/by/3.0/ + * @see http://www.geekality.net/?p=1614 + */ +public class LineReader implements Iterable, Closeable +{ + private BufferedReader reader; + + public LineReader(InputStream stream) { this(stream, null); } + public LineReader(InputStream stream, Charset charset) + { + reader = new BufferedReader(new InputStreamReader(stream, charset)); + } + + /** + * Closes the underlying stream. + */ + @Override + public void close() throws IOException + { + reader.close(); + } + + /** + * Makes sure the underlying stream is closed. + */ + @Override + protected void finalize() throws Throwable + { + close(); + } + + + /** + * Returns an iterator over the lines remaining to be read. + * + *

The underlying stream is closed automatically once {@link Iterator#hasNext()} + * returns false. This means that the stream should be closed after using a for loop. + * + * @return This iterator. + */ + @Override + public Iterator iterator() + { + return new LineIterator(); + } + + /** + * Returns all lines remaining to be read and closes the stream. + * + * @return The lines read from the stream. + */ + public Collection readLines() + { + Collection lines = new ArrayList(); + for(String line : this) + { + lines.add(line); + } + return lines; + } + + private class LineIterator implements Iterator + { + private String nextLine; + + public String bufferNext() + { + try + { + return nextLine = reader.readLine(); + } + catch (IOException e) + { + throw new IllegalStateException("I/O error while reading stream.", e); + } + } + + + public boolean hasNext() + { + boolean hasNext = nextLine != null || bufferNext() != null; + + if ( ! hasNext) + try + { + reader.close(); + } + catch (IOException e) + { + throw new IllegalStateException("I/O error when closing stream.", e); + } + + return hasNext; + } + + public String next() + { + if ( ! hasNext()) + throw new NoSuchElementException(); + + String result = nextLine; + nextLine = null; + return result; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } +} \ No newline at end of file diff --git a/src/main/java/forge/util/StorageReaderFile.java b/src/main/java/forge/util/StorageReaderFile.java index 9d8a4ce096c..c6665ede748 100644 --- a/src/main/java/forge/util/StorageReaderFile.java +++ b/src/main/java/forge/util/StorageReaderFile.java @@ -18,7 +18,6 @@ package forge.util; import java.io.File; -import java.util.ArrayList; import java.util.Map; import java.util.TreeMap; @@ -55,9 +54,8 @@ public abstract class StorageReaderFile implements IItemReader { @Override public Map readAll() { final Map result = new TreeMap(); - final ArrayList fData = FileUtil.readFile(this.file); - for (final String s : fData) { + for (final String s : FileUtil.readFile(this.file)) { if (!this.lineContainsObject(s)) { continue; }