From 29a535c71a5978afb94caed64fb1a9dbd6f6cdea Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Fri, 22 Nov 2013 16:51:38 +0000 Subject: [PATCH] moved CardStorageReader to core project --- .gitattributes | 5 +- .../main/java/forge}/CardStorageReader.java | 700 +++++++++--------- .../main/java/forge/ICardStorageReader.java | 14 - .../main/java/forge/IProgressObserver.java | 12 - .../src/main/java/forge/StaticData.java | 2 +- .../src/main/java/forge/util/ThreadUtil.java | 54 ++ forge-gui/src/main/java/forge/FThreads.java | 54 +- forge-gui/src/main/java/forge/Singletons.java | 5 +- .../src/main/java/forge/game/GameAction.java | 5 +- .../java/forge/gui/framework/SLayoutIO.java | 6 +- .../forge/gui/input/InputConfirmMulligan.java | 4 +- .../java/forge/gui/input/InputLockUI.java | 3 +- .../forge/gui/workshop/CardScriptInfo.java | 5 +- .../forge/view/CardReaderExperiments.java | 2 +- 14 files changed, 432 insertions(+), 439 deletions(-) rename {forge-gui/src/main/java/forge/card/cardfactory => forge-core/src/main/java/forge}/CardStorageReader.java (88%) delete mode 100644 forge-core/src/main/java/forge/ICardStorageReader.java delete mode 100644 forge-core/src/main/java/forge/IProgressObserver.java create mode 100644 forge-core/src/main/java/forge/util/ThreadUtil.java diff --git a/.gitattributes b/.gitattributes index a85179bec6a..6d781277a61 100644 --- a/.gitattributes +++ b/.gitattributes @@ -19,8 +19,7 @@ forge-core/.settings/org.eclipse.core.resources.prefs -text forge-core/.settings/org.eclipse.jdt.core.prefs -text forge-core/.settings/org.eclipse.m2e.core.prefs -text forge-core/pom.xml -text -forge-core/src/main/java/forge/ICardStorageReader.java -text -forge-core/src/main/java/forge/IProgressObserver.java -text +forge-core/src/main/java/forge/CardStorageReader.java -text forge-core/src/main/java/forge/StaticData.java -text forge-core/src/main/java/forge/card/BoosterGenerator.java svneol=native#text/plain forge-core/src/main/java/forge/card/BoosterSlots.java -text @@ -98,6 +97,7 @@ forge-core/src/main/java/forge/util/Lang.java -text forge-core/src/main/java/forge/util/MyRandom.java svneol=native#text/plain forge-core/src/main/java/forge/util/PredicateString.java -text forge-core/src/main/java/forge/util/TextUtil.java -text +forge-core/src/main/java/forge/util/ThreadUtil.java -text forge-core/src/main/java/forge/util/package-info.java -text forge-core/src/main/java/forge/util/storage/IStorage.java -text forge-core/src/main/java/forge/util/storage/StorageBase.java -text @@ -14944,7 +14944,6 @@ forge-gui/src/main/java/forge/card/ability/package-info.java svneol=native#text/ forge-gui/src/main/java/forge/card/cardfactory/CardFactory.java svneol=native#text/plain forge-gui/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java svneol=native#text/plain forge-gui/src/main/java/forge/card/cardfactory/CardFactoryUtil.java svneol=native#text/plain -forge-gui/src/main/java/forge/card/cardfactory/CardStorageReader.java svneol=native#text/plain forge-gui/src/main/java/forge/card/cardfactory/package-info.java svneol=native#text/plain forge-gui/src/main/java/forge/card/cost/Cost.java svneol=native#text/plain forge-gui/src/main/java/forge/card/cost/CostAddMana.java -text diff --git a/forge-gui/src/main/java/forge/card/cardfactory/CardStorageReader.java b/forge-core/src/main/java/forge/CardStorageReader.java similarity index 88% rename from forge-gui/src/main/java/forge/card/cardfactory/CardStorageReader.java rename to forge-core/src/main/java/forge/CardStorageReader.java index 74c548fac0a..c9f454edcca 100644 --- a/forge-gui/src/main/java/forge/card/cardfactory/CardStorageReader.java +++ b/forge-core/src/main/java/forge/CardStorageReader.java @@ -1,344 +1,356 @@ -/* - * Forge: Play Magic: the Gathering. - * Copyright (C) 2011 Forge Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package forge.card.cardfactory; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import org.apache.commons.lang3.time.StopWatch; - -import forge.FThreads; -import forge.ICardStorageReader; -import forge.IProgressObserver; -import forge.card.CardRules; -import forge.util.FileUtil; - -/** - *

- * CardReader class. - *

- * - * @author Forge - * @version $Id$ - */ - -public class CardStorageReader implements ICardStorageReader { - - private static final String CARD_FILE_DOT_EXTENSION = ".txt"; - - /** Default charset when loading from files. */ - public static final String DEFAULT_CHARSET_NAME = "US-ASCII"; - - private final boolean useThreadPool = FThreads.isMultiCoreSystem(); - public final static int NUMBER_OF_PARTS = 25; - - private final CountDownLatch cdl = new CountDownLatch(NUMBER_OF_PARTS); - private final IProgressObserver progressObserver; - - private transient File cardsfolder; - - private transient ZipFile zip; - private final transient Charset charset; - - private final Observer observer; - - - // 8/18/11 10:56 PM - - - /** - *

- * Constructor for CardReader. - *

- * - * @param theCardsFolder - * indicates location of the cardsFolder - * @param useZip - * if true, attempts to load cards from a zip file, if one - * exists. - */ - public CardStorageReader(String cardDataDir, final boolean useZip, IProgressObserver progressObserver, ICardStorageReader.Observer observer) { - this.progressObserver = progressObserver != null ? progressObserver : IProgressObserver.emptyObserver; - this.cardsfolder = new File(cardDataDir); - this.observer = observer; - - // These read data for lightweight classes. - if (!cardsfolder.exists()) { - throw new RuntimeException("CardReader : constructor error -- " + cardsfolder.getAbsolutePath() + " file/folder not found."); - } - - if (!cardsfolder.isDirectory()) { - throw new RuntimeException("CardReader : constructor error -- not a directory -- " + cardsfolder.getAbsolutePath()); - } - - final File zipFile = new File(cardsfolder, "cardsfolder.zip"); - - if (useZip && zipFile.exists()) { - try { - this.zip = new ZipFile(zipFile); - } catch (final Exception exn) { - System.err.printf("Error reading zip file \"%s\": %s. Defaulting to txt files in \"%s\".%n", zipFile.getAbsolutePath(), exn, cardsfolder.getAbsolutePath()); - } - } - - this.charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME); - - } // CardReader() - - private final List loadCardsInRange(final List files, int from, int to) { - CardRules.Reader rulesReader = new CardRules.Reader(); - - List result = new ArrayList(); - for(int i = from; i < to; i++) { - File cardTxtFile = files.get(i); - result.add(this.loadCard(rulesReader, cardTxtFile)); - } - return result; - } - - private final List loadCardsInRangeFromZip(final List files, int from, int to) { - CardRules.Reader rulesReader = new CardRules.Reader(); - - List result = new ArrayList(); - for(int i = from; i < to; i++) { - ZipEntry ze = files.get(i); - // if (ze.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) // already filtered! - result.add(this.loadCard(rulesReader, ze)); - } - return result; - } - - /** - * Starts reading cards into memory until the given card is found. - * - * After that, we save our place in the list of cards (on disk) in case we - * need to load more. - * - * @return the Card or null if it was not found. - */ - public final List loadCards() { - progressObserver.setOperationName("Loading card data", true); - progressObserver.report(0, NUMBER_OF_PARTS); - - final List>> tasks; - long estimatedFilesRemaining; - - // Iterate through txt files or zip archive. - // Report relevant numbers to progress monitor model. - if (this.zip == null) { - final List allFiles = collectCardFiles(new ArrayList(), this.cardsfolder); - estimatedFilesRemaining = allFiles.size(); - tasks = makeTaskListForFiles(allFiles); - } else { - estimatedFilesRemaining = this.zip.size(); - ZipEntry entry; - List entries = new ArrayList(); - // zipEnum was initialized in the constructor. - Enumeration zipEnum = this.zip.entries(); - while (zipEnum.hasMoreElements()) { - entry = zipEnum.nextElement(); - if (entry.isDirectory() || !entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) - continue; - entries.add(entry); - } - - tasks = makeTaskListForZip(entries); - } // endif - - StopWatch sw = new StopWatch(); - sw.start(); - - List res = executeLoadTask(tasks); - - sw.stop(); - final long timeOnParse = sw.getTime(); - System.out.printf("Read cards: %s %s in %d ms (%d parts) %s%n", estimatedFilesRemaining, zip == null? "files" : "archived files", timeOnParse, NUMBER_OF_PARTS, useThreadPool ? "using thread pool" : "in same thread"); -// if ( null != barProgress ) -// barProgress.setPercentMode(false); - return res; - } // loadCardsUntilYouFind(String) - - private List executeLoadTask(final List>> tasks) { - List result = new ArrayList(); - - try { - if ( useThreadPool ) { - final ExecutorService executor = FThreads.getComputingPool(0.5f); - final List>> parts = executor.invokeAll(tasks); - executor.shutdown(); - cdl.await(); - for(Future> pp : parts) { - result.addAll(pp.get()); - } - } else { - for(Callable> c : tasks) { - result.addAll(c.call()); - } - } - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } catch (Exception e) { // this clause comes from non-threaded branch - throw new RuntimeException(e); - } - - return result; - } - - private List>> makeTaskListForZip(final List entries) { - int totalFiles = entries.size(); - int filesPerPart = totalFiles / NUMBER_OF_PARTS; - final List>> tasks = new ArrayList>>(); - for (int iPart = 0; iPart < NUMBER_OF_PARTS; iPart++) { - final int from = iPart * filesPerPart; - final int till = iPart == NUMBER_OF_PARTS - 1 ? totalFiles : from + filesPerPart; - tasks.add(new Callable>() { - @Override - public List call() throws Exception{ - List res = loadCardsInRangeFromZip(entries, from, till); - cdl.countDown(); - progressObserver.report(NUMBER_OF_PARTS - (int)cdl.getCount(), NUMBER_OF_PARTS); - return res; - } - }); - } - return tasks; - } - - private List>> makeTaskListForFiles(final List allFiles) { - int totalFiles = allFiles.size(); - int filesPerPart = totalFiles / NUMBER_OF_PARTS; - final List>> tasks = new ArrayList>>(); - for (int iPart = 0; iPart < NUMBER_OF_PARTS; iPart++) { - final int from = iPart * filesPerPart; - final int till = iPart == NUMBER_OF_PARTS - 1 ? totalFiles : from + filesPerPart; - tasks.add(new Callable>() { - @Override - public List call() throws Exception{ - List res = loadCardsInRange(allFiles, from, till); - cdl.countDown(); - progressObserver.report(NUMBER_OF_PARTS - (int)cdl.getCount(), NUMBER_OF_PARTS); - return res; - } - }); - } - return tasks; - } - - public static List collectCardFiles(List accumulator, File startDir) { - String[] list = startDir.list(); - for (String filename : list) { - File entry = new File(startDir, filename); - - if (!entry.isDirectory()) { - if (entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) - accumulator.add(entry); - continue; - } - if (filename.startsWith(".")) { - continue; - } - - collectCardFiles(accumulator, entry); - } - return accumulator; - } - - - private List readScript(final InputStream inputStream) { - return FileUtil.readAllLines(new InputStreamReader(inputStream, this.charset), true); - } - - /** - * Load a card from a txt file. - * - * @param pathToTxtFile - * the full or relative path to the file to load - * - * @return a new Card instance - */ - protected final CardRules loadCard(final CardRules.Reader reader, final File file) { - FileInputStream fileInputStream = null; - try { - fileInputStream = new FileInputStream(file); - reader.reset(); - List lines = readScript(fileInputStream); - CardRules rules = reader.readCard(lines); - if ( null != observer ) - observer.cardLoaded(rules, lines, file); - return rules; - } catch (final FileNotFoundException ex) { - throw new RuntimeException("CardReader : run error -- file not found: " + file.getPath(), ex); - } finally { - try { - fileInputStream.close(); - } catch (final IOException ignored) { - // 11:08 - // PM - } - } - } - - /** - * Load a card from an entry in a zip file. - * - * @param entry - * to load from - * - * @return a new Card instance - */ - protected final CardRules loadCard(final CardRules.Reader rulesReader, final ZipEntry entry) { - InputStream zipInputStream = null; - try { - zipInputStream = this.zip.getInputStream(entry); - rulesReader.reset(); - CardRules rules = rulesReader.readCard(readScript(zipInputStream)); - - return rules; - } catch (final IOException exn) { - throw new RuntimeException(exn); - // PM - } finally { - try { - if (zipInputStream != null) { - zipInputStream.close(); - } - } catch (final IOException ignored) { - // 11:08 - // PM - } - } - } - -} +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package forge; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.apache.commons.lang3.time.StopWatch; + +import forge.card.CardRules; +import forge.util.FileUtil; +import forge.util.ThreadUtil; + +/** + *

+ * CardReader class. + *

+ * + * @author Forge + * @version $Id: CardStorageReader.java 23742 2013-11-22 16:32:56Z Max mtg $ + */ + +public class CardStorageReader { + public interface Observer { + public void cardLoaded(CardRules rules, List lines, File fileOnDisk); + } + + public interface ProgressObserver{ + void setOperationName(String name, boolean usePercents); + void report(int current, int total); + + // does nothing, used when they pass null instead of an instance + public final static ProgressObserver emptyObserver = new ProgressObserver() { + @Override public void setOperationName(String name, boolean usePercents) {} + @Override public void report(int current, int total) {} + }; + } + + private static final String CARD_FILE_DOT_EXTENSION = ".txt"; + + /** Default charset when loading from files. */ + public static final String DEFAULT_CHARSET_NAME = "US-ASCII"; + + private final boolean useThreadPool = ThreadUtil.isMultiCoreSystem(); + public final static int NUMBER_OF_PARTS = 25; + + private final CountDownLatch cdl = new CountDownLatch(NUMBER_OF_PARTS); + private final ProgressObserver progressObserver; + + private transient File cardsfolder; + + private transient ZipFile zip; + private final transient Charset charset; + + private final Observer observer; + + + // 8/18/11 10:56 PM + + + /** + *

+ * Constructor for CardReader. + *

+ * + * @param theCardsFolder + * indicates location of the cardsFolder + * @param useZip + * if true, attempts to load cards from a zip file, if one + * exists. + */ + public CardStorageReader(String cardDataDir, final boolean useZip, CardStorageReader.ProgressObserver progressObserver, Observer observer) { + this.progressObserver = progressObserver != null ? progressObserver : CardStorageReader.ProgressObserver.emptyObserver; + this.cardsfolder = new File(cardDataDir); + this.observer = observer; + + // These read data for lightweight classes. + if (!cardsfolder.exists()) { + throw new RuntimeException("CardReader : constructor error -- " + cardsfolder.getAbsolutePath() + " file/folder not found."); + } + + if (!cardsfolder.isDirectory()) { + throw new RuntimeException("CardReader : constructor error -- not a directory -- " + cardsfolder.getAbsolutePath()); + } + + final File zipFile = new File(cardsfolder, "cardsfolder.zip"); + + if (useZip && zipFile.exists()) { + try { + this.zip = new ZipFile(zipFile); + } catch (final Exception exn) { + System.err.printf("Error reading zip file \"%s\": %s. Defaulting to txt files in \"%s\".%n", zipFile.getAbsolutePath(), exn, cardsfolder.getAbsolutePath()); + } + } + + this.charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME); + + } // CardReader() + + private final List loadCardsInRange(final List files, int from, int to) { + CardRules.Reader rulesReader = new CardRules.Reader(); + + List result = new ArrayList(); + for(int i = from; i < to; i++) { + File cardTxtFile = files.get(i); + result.add(this.loadCard(rulesReader, cardTxtFile)); + } + return result; + } + + private final List loadCardsInRangeFromZip(final List files, int from, int to) { + CardRules.Reader rulesReader = new CardRules.Reader(); + + List result = new ArrayList(); + for(int i = from; i < to; i++) { + ZipEntry ze = files.get(i); + // if (ze.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) // already filtered! + result.add(this.loadCard(rulesReader, ze)); + } + return result; + } + + /** + * Starts reading cards into memory until the given card is found. + * + * After that, we save our place in the list of cards (on disk) in case we + * need to load more. + * + * @return the Card or null if it was not found. + */ + public final List loadCards() { + progressObserver.setOperationName("Loading card data", true); + progressObserver.report(0, NUMBER_OF_PARTS); + + final List>> tasks; + long estimatedFilesRemaining; + + // Iterate through txt files or zip archive. + // Report relevant numbers to progress monitor model. + if (this.zip == null) { + final List allFiles = collectCardFiles(new ArrayList(), this.cardsfolder); + estimatedFilesRemaining = allFiles.size(); + tasks = makeTaskListForFiles(allFiles); + } else { + estimatedFilesRemaining = this.zip.size(); + ZipEntry entry; + List entries = new ArrayList(); + // zipEnum was initialized in the constructor. + Enumeration zipEnum = this.zip.entries(); + while (zipEnum.hasMoreElements()) { + entry = zipEnum.nextElement(); + if (entry.isDirectory() || !entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) + continue; + entries.add(entry); + } + + tasks = makeTaskListForZip(entries); + } // endif + + StopWatch sw = new StopWatch(); + sw.start(); + + List res = executeLoadTask(tasks); + + sw.stop(); + final long timeOnParse = sw.getTime(); + System.out.printf("Read cards: %s %s in %d ms (%d parts) %s%n", estimatedFilesRemaining, zip == null? "files" : "archived files", timeOnParse, NUMBER_OF_PARTS, useThreadPool ? "using thread pool" : "in same thread"); +// if ( null != barProgress ) +// barProgress.setPercentMode(false); + return res; + } // loadCardsUntilYouFind(String) + + private List executeLoadTask(final List>> tasks) { + List result = new ArrayList(); + + try { + if ( useThreadPool ) { + final ExecutorService executor = ThreadUtil.getComputingPool(0.5f); + final List>> parts = executor.invokeAll(tasks); + executor.shutdown(); + cdl.await(); + for(Future> pp : parts) { + result.addAll(pp.get()); + } + } else { + for(Callable> c : tasks) { + result.addAll(c.call()); + } + } + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } catch (Exception e) { // this clause comes from non-threaded branch + throw new RuntimeException(e); + } + + return result; + } + + private List>> makeTaskListForZip(final List entries) { + int totalFiles = entries.size(); + int filesPerPart = totalFiles / NUMBER_OF_PARTS; + final List>> tasks = new ArrayList>>(); + for (int iPart = 0; iPart < NUMBER_OF_PARTS; iPart++) { + final int from = iPart * filesPerPart; + final int till = iPart == NUMBER_OF_PARTS - 1 ? totalFiles : from + filesPerPart; + tasks.add(new Callable>() { + @Override + public List call() throws Exception{ + List res = loadCardsInRangeFromZip(entries, from, till); + cdl.countDown(); + progressObserver.report(NUMBER_OF_PARTS - (int)cdl.getCount(), NUMBER_OF_PARTS); + return res; + } + }); + } + return tasks; + } + + private List>> makeTaskListForFiles(final List allFiles) { + int totalFiles = allFiles.size(); + int filesPerPart = totalFiles / NUMBER_OF_PARTS; + final List>> tasks = new ArrayList>>(); + for (int iPart = 0; iPart < NUMBER_OF_PARTS; iPart++) { + final int from = iPart * filesPerPart; + final int till = iPart == NUMBER_OF_PARTS - 1 ? totalFiles : from + filesPerPart; + tasks.add(new Callable>() { + @Override + public List call() throws Exception{ + List res = loadCardsInRange(allFiles, from, till); + cdl.countDown(); + progressObserver.report(NUMBER_OF_PARTS - (int)cdl.getCount(), NUMBER_OF_PARTS); + return res; + } + }); + } + return tasks; + } + + public static List collectCardFiles(List accumulator, File startDir) { + String[] list = startDir.list(); + for (String filename : list) { + File entry = new File(startDir, filename); + + if (!entry.isDirectory()) { + if (entry.getName().endsWith(CardStorageReader.CARD_FILE_DOT_EXTENSION)) + accumulator.add(entry); + continue; + } + if (filename.startsWith(".")) { + continue; + } + + collectCardFiles(accumulator, entry); + } + return accumulator; + } + + + private List readScript(final InputStream inputStream) { + return FileUtil.readAllLines(new InputStreamReader(inputStream, this.charset), true); + } + + /** + * Load a card from a txt file. + * + * @param pathToTxtFile + * the full or relative path to the file to load + * + * @return a new Card instance + */ + protected final CardRules loadCard(final CardRules.Reader reader, final File file) { + FileInputStream fileInputStream = null; + try { + fileInputStream = new FileInputStream(file); + reader.reset(); + List lines = readScript(fileInputStream); + CardRules rules = reader.readCard(lines); + if ( null != observer ) + observer.cardLoaded(rules, lines, file); + return rules; + } catch (final FileNotFoundException ex) { + throw new RuntimeException("CardReader : run error -- file not found: " + file.getPath(), ex); + } finally { + try { + fileInputStream.close(); + } catch (final IOException ignored) { + // 11:08 + // PM + } + } + } + + /** + * Load a card from an entry in a zip file. + * + * @param entry + * to load from + * + * @return a new Card instance + */ + protected final CardRules loadCard(final CardRules.Reader rulesReader, final ZipEntry entry) { + InputStream zipInputStream = null; + try { + zipInputStream = this.zip.getInputStream(entry); + rulesReader.reset(); + CardRules rules = rulesReader.readCard(readScript(zipInputStream)); + + return rules; + } catch (final IOException exn) { + throw new RuntimeException(exn); + // PM + } finally { + try { + if (zipInputStream != null) { + zipInputStream.close(); + } + } catch (final IOException ignored) { + // 11:08 + // PM + } + } + } + +} diff --git a/forge-core/src/main/java/forge/ICardStorageReader.java b/forge-core/src/main/java/forge/ICardStorageReader.java deleted file mode 100644 index c705faf5506..00000000000 --- a/forge-core/src/main/java/forge/ICardStorageReader.java +++ /dev/null @@ -1,14 +0,0 @@ -package forge; - -import java.io.File; -import java.util.List; - -import forge.card.CardRules; - -public interface ICardStorageReader { - List loadCards(); - - public interface Observer { - public void cardLoaded(CardRules rules, List lines, File fileOnDisk); - } -} \ No newline at end of file diff --git a/forge-core/src/main/java/forge/IProgressObserver.java b/forge-core/src/main/java/forge/IProgressObserver.java deleted file mode 100644 index 4318e216ce9..00000000000 --- a/forge-core/src/main/java/forge/IProgressObserver.java +++ /dev/null @@ -1,12 +0,0 @@ -package forge; - -public interface IProgressObserver{ - void setOperationName(String name, boolean usePercents); - void report(int current, int total); - - // does nothing, used when they pass null instead of an instance - public final static IProgressObserver emptyObserver = new IProgressObserver() { - @Override public void setOperationName(String name, boolean usePercents) {} - @Override public void report(int current, int total) {} - }; -} \ No newline at end of file diff --git a/forge-core/src/main/java/forge/StaticData.java b/forge-core/src/main/java/forge/StaticData.java index f30af6b4f6b..ecebe56244a 100644 --- a/forge-core/src/main/java/forge/StaticData.java +++ b/forge-core/src/main/java/forge/StaticData.java @@ -32,7 +32,7 @@ public class StaticData { private static StaticData lastInstance = null; - public StaticData(ICardStorageReader reader, String editionFolder, String blockDataFolder) { + public StaticData(CardStorageReader reader, String editionFolder, String blockDataFolder) { this.editions = new CardEdition.Collection(new CardEdition.Reader(new File(editionFolder))); lastInstance = this; diff --git a/forge-core/src/main/java/forge/util/ThreadUtil.java b/forge-core/src/main/java/forge/util/ThreadUtil.java new file mode 100644 index 00000000000..6e02ef9e794 --- /dev/null +++ b/forge-core/src/main/java/forge/util/ThreadUtil.java @@ -0,0 +1,54 @@ +package forge.util; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +public class ThreadUtil { + + static { + System.out.printf("(ThreadUtil first call): Running on a machine with %d cpu core(s)%n", Runtime.getRuntime().availableProcessors() ); + } + + private static class WorkerThreadFactory implements ThreadFactory { + private int countr = 0; + private String prefix = ""; + + public WorkerThreadFactory(String prefix) { + this.prefix = prefix; + } + + public Thread newThread(Runnable r) { + return new Thread(r, prefix + "-" + countr++); + } + } + + + + private final static ExecutorService gameThreadPool = Executors.newCachedThreadPool(new WorkerThreadFactory("Game")); + private static ExecutorService getGameThreadPool() { return gameThreadPool; } + private final static ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2, new WorkerThreadFactory("Delayed")); + private static ScheduledExecutorService getScheduledPool() { return scheduledPool; } + + // This pool is designed to parallel CPU or IO intensive tasks like parse cards or download images, assuming a load factor of 0.5 + public final static ExecutorService getComputingPool(float loadFactor) { + return Executors.newFixedThreadPool((int)(Runtime.getRuntime().availableProcessors() / (1-loadFactor))); + } + + public static boolean isMultiCoreSystem() { + return Runtime.getRuntime().availableProcessors() > 1; + } + + public static void invokeInGameThread(Runnable toRun) { + getGameThreadPool().execute(toRun); + } + public static void delay(int milliseconds, Runnable inputUpdater) { + getScheduledPool().schedule(inputUpdater, milliseconds, TimeUnit.MILLISECONDS); + } + + public static boolean isGameThread() { + return Thread.currentThread().getName().startsWith("Game"); + } +} \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/FThreads.java b/forge-gui/src/main/java/forge/FThreads.java index f279082e448..bb980772560 100644 --- a/forge-gui/src/main/java/forge/FThreads.java +++ b/forge-gui/src/main/java/forge/FThreads.java @@ -2,53 +2,18 @@ package forge; import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; import javax.swing.SwingUtilities; +import forge.util.ThreadUtil; + /** * TODO: Write javadoc for this type. * */ public class FThreads { - static { - System.out.printf("(FThreads static ctor): Running on a machine with %d cpu core(s)%n", Runtime.getRuntime().availableProcessors() ); - } - - private static class WorkerThreadFactory implements ThreadFactory { - private int countr = 0; - private String prefix = ""; - - public WorkerThreadFactory(String prefix) { - this.prefix = prefix; - } - - public Thread newThread(Runnable r) { - return new Thread(r, prefix + "-" + countr++); - } - } - private FThreads() { } // no instances supposed - - private final static ExecutorService gameThreadPool = Executors.newCachedThreadPool(new WorkerThreadFactory("Game")); - private static ExecutorService getGameThreadPool() { return gameThreadPool; } - private final static ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2, new WorkerThreadFactory("Delayed")); - private static ScheduledExecutorService getScheduledPool() { return scheduledPool; } - - // This pool is designed to parallel CPU or IO intensive tasks like parse cards or download images, assuming a load factor of 0.5 - public final static ExecutorService getComputingPool(float loadFactor) { - return Executors.newFixedThreadPool((int)(Runtime.getRuntime().availableProcessors() / (1-loadFactor))); - } - - public static boolean isMultiCoreSystem() { - return Runtime.getRuntime().availableProcessors() > 1; - } - /** Checks if calling method uses event dispatch thread. * Exception thrown if method is on "wrong" thread. * A boolean is passed to indicate if the method must be EDT or not. @@ -111,9 +76,7 @@ public class FThreads { } - public static void invokeInGameThread(Runnable toRun) { - getGameThreadPool().execute(toRun); - } + /** * TODO: Write javadoc for this method. @@ -124,17 +87,13 @@ public class FThreads { } - public static void delay(int milliseconds, Runnable inputUpdater) { - getScheduledPool().schedule(inputUpdater, milliseconds, TimeUnit.MILLISECONDS); - } - public static void delayInEDT(int milliseconds, final Runnable inputUpdater) { Runnable runInEdt = new Runnable() { @Override public void run() { FThreads.invokeInEdtNowOrLater(inputUpdater); } }; - delay(milliseconds, runInEdt); + ThreadUtil.delay(milliseconds, runInEdt); } public static String debugGetCurrThreadId() { @@ -171,9 +130,4 @@ public class FThreads { public static String debugGetStackTraceItem(int depth) { return debugGetStackTraceItem(depth, false); } - - public static boolean isGameThread() { - return Thread.currentThread().getName().startsWith("Game"); - } - } diff --git a/forge-gui/src/main/java/forge/Singletons.java b/forge-gui/src/main/java/forge/Singletons.java index cf40c270965..589f4293c1d 100644 --- a/forge-gui/src/main/java/forge/Singletons.java +++ b/forge-gui/src/main/java/forge/Singletons.java @@ -17,11 +17,9 @@ */ package forge; -import forge.card.cardfactory.CardStorageReader; import forge.control.FControl; import forge.gui.toolbox.FProgressBar; import forge.gui.workshop.CardScriptInfo; -import forge.gui.workshop.controllers.CCardScript; import forge.model.FModel; import forge.properties.NewConstants; import forge.view.FView; @@ -57,7 +55,8 @@ public final class Singletons { if(withUi) view = FView.SINGLETON_INSTANCE; - IProgressObserver progressBarBridge = view == null ? IProgressObserver.emptyObserver : new IProgressObserver() { + CardStorageReader.ProgressObserver progressBarBridge = view == null + ? CardStorageReader.ProgressObserver.emptyObserver : new CardStorageReader.ProgressObserver() { FProgressBar bar = view.getSplash().getProgressBar(); @Override public void setOperationName(final String name, final boolean usePercents) { diff --git a/forge-gui/src/main/java/forge/game/GameAction.java b/forge-gui/src/main/java/forge/game/GameAction.java index 46c46c7119f..4a84ebd847f 100644 --- a/forge-gui/src/main/java/forge/game/GameAction.java +++ b/forge-gui/src/main/java/forge/game/GameAction.java @@ -75,6 +75,7 @@ import forge.game.zone.Zone; import forge.game.zone.ZoneType; import forge.util.Aggregates; import forge.util.CollectionSuppliers; +import forge.util.ThreadUtil; import forge.util.maps.HashMapOfLists; import forge.util.maps.MapOfLists; @@ -1620,10 +1621,10 @@ public class GameAction { // Invokes given runnable in Game thread pool - used to start game and perform actions from UI (when game-0 waits for input) public void invoke(final Runnable proc) { - if( FThreads.isGameThread() ) { + if( ThreadUtil.isGameThread() ) { proc.run(); } else - FThreads.invokeInGameThread(proc); + ThreadUtil.invokeInGameThread(proc); } } diff --git a/forge-gui/src/main/java/forge/gui/framework/SLayoutIO.java b/forge-gui/src/main/java/forge/gui/framework/SLayoutIO.java index 15b80f71f0f..41706368c47 100644 --- a/forge-gui/src/main/java/forge/gui/framework/SLayoutIO.java +++ b/forge-gui/src/main/java/forge/gui/framework/SLayoutIO.java @@ -26,12 +26,12 @@ import javax.xml.stream.events.Attribute; import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; -import forge.FThreads; import forge.Singletons; import forge.gui.toolbox.FAbsolutePositioner; import forge.properties.FileLocation; import forge.properties.NewConstants; import forge.util.CollectionSuppliers; +import forge.util.ThreadUtil; import forge.util.maps.HashMapOfLists; import forge.util.maps.MapOfLists; import forge.view.FFrame; @@ -63,7 +63,7 @@ public final class SLayoutIO { public static void saveWindowLayout() { if (saveWindowRequested.getAndSet(true)) { return; } - FThreads.delay(500, new Runnable() { + ThreadUtil.delay(500, new Runnable() { @Override public void run() { finishSaveWindowLayout(); @@ -230,7 +230,7 @@ public final class SLayoutIO { */ public static void saveLayout(final File f0) { if( saveRequested.getAndSet(true) ) return; - FThreads.delay(100, new Runnable() { + ThreadUtil.delay(100, new Runnable() { @Override public void run() { diff --git a/forge-gui/src/main/java/forge/gui/input/InputConfirmMulligan.java b/forge-gui/src/main/java/forge/gui/input/InputConfirmMulligan.java index eb67ad89ae2..27e3438efc1 100644 --- a/forge-gui/src/main/java/forge/gui/input/InputConfirmMulligan.java +++ b/forge-gui/src/main/java/forge/gui/input/InputConfirmMulligan.java @@ -22,13 +22,13 @@ import java.util.ArrayList; import java.util.List; import forge.Card; -import forge.FThreads; import forge.game.Game; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiDialog; import forge.gui.match.CMatchUI; import forge.util.Lang; +import forge.util.ThreadUtil; import forge.view.ButtonUtil; /** *

@@ -122,7 +122,7 @@ public class InputConfirmMulligan extends InputSyncronizedBase { if ( isSerumPowder && GuiDialog.confirm(c0, "Use " + c0.getName() + "'s ability?")) { cardSelectLocked = true; - FThreads.invokeInGameThread(new Runnable() { + ThreadUtil.invokeInGameThread(new Runnable() { public void run() { List hand = new ArrayList(c0.getController().getCardsIn(ZoneType.Hand)); for (Card c : hand) { diff --git a/forge-gui/src/main/java/forge/gui/input/InputLockUI.java b/forge-gui/src/main/java/forge/gui/input/InputLockUI.java index cb5a4beeef0..2755398fad8 100644 --- a/forge-gui/src/main/java/forge/gui/input/InputLockUI.java +++ b/forge-gui/src/main/java/forge/gui/input/InputLockUI.java @@ -10,6 +10,7 @@ import forge.card.spellability.SpellAbility; import forge.control.InputQueue; import forge.game.player.Player; import forge.gui.match.CMatchUI; +import forge.util.ThreadUtil; import forge.view.ButtonUtil; /** @@ -24,7 +25,7 @@ public class InputLockUI implements Input { public void showMessageInitial() { int ixCall = 1 + iCall.getAndIncrement(); - FThreads.delay(500, new InputUpdater(ixCall)); + ThreadUtil.delay(500, new InputUpdater(ixCall)); } @Override diff --git a/forge-gui/src/main/java/forge/gui/workshop/CardScriptInfo.java b/forge-gui/src/main/java/forge/gui/workshop/CardScriptInfo.java index 0635bdcf33f..70c72fc65b8 100644 --- a/forge-gui/src/main/java/forge/gui/workshop/CardScriptInfo.java +++ b/forge-gui/src/main/java/forge/gui/workshop/CardScriptInfo.java @@ -20,12 +20,11 @@ package forge.gui.workshop; import java.io.File; import java.util.List; import java.util.Map; -import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.lang3.StringUtils; -import forge.ICardStorageReader; +import forge.CardStorageReader; import forge.card.CardRules; public final class CardScriptInfo { @@ -58,7 +57,7 @@ public final class CardScriptInfo { return allScrips.get(name); } - public static ICardStorageReader.Observer readerObserver = new ICardStorageReader.Observer() { + public static CardStorageReader.Observer readerObserver = new CardStorageReader.Observer() { @Override public void cardLoaded(CardRules rules, List lines, File fileOnDisk) { allScrips.put(rules.getName(), new CardScriptInfo(StringUtils.join(lines, '\n'), fileOnDisk)); diff --git a/forge-gui/src/main/java/forge/view/CardReaderExperiments.java b/forge-gui/src/main/java/forge/view/CardReaderExperiments.java index bf1e610f072..262108b681e 100644 --- a/forge-gui/src/main/java/forge/view/CardReaderExperiments.java +++ b/forge-gui/src/main/java/forge/view/CardReaderExperiments.java @@ -11,8 +11,8 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import forge.CardStorageReader; import forge.card.CardRules; -import forge.card.cardfactory.CardStorageReader; import forge.properties.NewConstants; import forge.util.FileUtil;