/* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ package mage.cards.repository; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.DaoManager; import com.j256.ormlite.jdbc.JdbcConnectionSource; import com.j256.ormlite.stmt.QueryBuilder; import com.j256.ormlite.stmt.SelectArg; import com.j256.ormlite.stmt.Where; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.support.DatabaseConnection; import com.j256.ormlite.table.TableUtils; import java.io.File; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.Callable; import mage.constants.CardType; import org.apache.log4j.Logger; /** * * @author North */ public enum CardRepository { instance; private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE"; private static final String VERSION_ENTITY_NAME = "card"; // raise this if db structure was changed private static final long CARD_DB_VERSION = 39; // raise this if new cards were added to the server private static final long CARD_CONTENT_VERSION = 19; private final Random random = new Random(); private Dao cardDao; private Set classNames; private CardRepository() { File file = new File("db"); if (!file.exists()) { file.mkdirs(); } try { ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL); boolean obsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, CARD_DB_VERSION); if (obsolete) { TableUtils.dropTable(connectionSource, CardInfo.class, true); } TableUtils.createTableIfNotExists(connectionSource, CardInfo.class); cardDao = DaoManager.createDao(connectionSource, CardInfo.class); } catch (SQLException ex) { ex.printStackTrace(); } } public void addCards(final List cards) { try { cardDao.callBatchTasks(new Callable() { @Override public Object call() throws Exception { try { for (CardInfo card : cards) { cardDao.create(card); if (classNames != null) { classNames.add(card.getClassName()); } } } catch (SQLException ex) { Logger.getLogger(CardRepository.class).error("Error adding cards to DB: " + ex.getCause()); } return null; } }); } catch (Exception ex) { } } public boolean cardExists(String className) { try { if (classNames == null) { QueryBuilder qb = cardDao.queryBuilder(); qb.distinct().selectColumns("className").where().isNotNull("className"); List results = cardDao.query(qb.prepare()); classNames = new TreeSet<>(); for (CardInfo card : results) { classNames.add(card.getClassName()); } } return classNames.contains(className); } catch (SQLException ex) { } return false; } public Set getNames() { Set names = new TreeSet<>(); try { QueryBuilder qb = cardDao.queryBuilder(); qb.distinct().selectColumns("name"); List results = cardDao.query(qb.prepare()); for (CardInfo card : results) { int result = card.getName().indexOf(" // "); if (result > 0) { names.add(card.getName().substring(0, result)); names.add(card.getName().substring(result+4)); } else { names.add(card.getName()); } } } catch (SQLException ex) { } return names; } public Set getNonLandNames() { Set names = new TreeSet<>(); try { QueryBuilder qb = cardDao.queryBuilder(); qb.distinct().selectColumns("name"); qb.where().not().like("types", new SelectArg('%' + CardType.LAND.name() + '%')); List results = cardDao.query(qb.prepare()); for (CardInfo card : results) { int result = card.getName().indexOf(" // "); if (result > 0) { names.add(card.getName().substring(0, result)); names.add(card.getName().substring(result+4)); } else { names.add(card.getName()); } } } catch (SQLException ex) { } return names; } public Set getCreatureNames() { Set names = new TreeSet<>(); try { QueryBuilder qb = cardDao.queryBuilder(); qb.distinct().selectColumns("name"); qb.where().like("types", new SelectArg('%' + CardType.CREATURE.name() + '%')); List results = cardDao.query(qb.prepare()); for (CardInfo card : results) { int result = card.getName().indexOf(" // "); if (result > 0) { names.add(card.getName().substring(0, result)); names.add(card.getName().substring(result+4)); } else { names.add(card.getName()); } } } catch (SQLException ex) { } return names; } public Set getNonLandAndNonCreatureNames() { Set names = new TreeSet<>(); try { QueryBuilder qb = cardDao.queryBuilder(); qb.distinct().selectColumns("name"); Where where = qb.where(); where.and(where.not().like("types", '%' + CardType.CREATURE.name() +'%'),where.not().like("types", '%' + CardType.LAND.name() + '%')); List results = cardDao.query(qb.prepare()); for (CardInfo card : results) { int result = card.getName().indexOf(" // "); if (result > 0) { names.add(card.getName().substring(0, result)); names.add(card.getName().substring(result + 4)); } else { names.add(card.getName()); } } } catch (SQLException ex) { } return names; } public Set getCreatureTypes() { TreeSet subtypes = new TreeSet<>(); try { QueryBuilder qb = cardDao.queryBuilder(); qb.distinct().selectColumns("subtypes"); qb.where().like("types", new SelectArg('%' + CardType.CREATURE.name() + '%')); List results = cardDao.query(qb.prepare()); for (CardInfo card : results) { subtypes.addAll(card.getSubTypes()); } // Removing Forest because of Dryad Arbor subtypes.remove("Forest"); // Some creature types are not directly included in card types and are added here manually subtypes.add("Blinkmoth"); subtypes.add("Camarid"); subtypes.add("Caribou"); subtypes.add("Citizen"); subtypes.add("Coward"); subtypes.add("Deserter"); subtypes.add("Germ"); subtypes.add("Graveborn"); subtypes.add("Orb"); subtypes.add("Pentavite"); subtypes.add("Pincher"); subtypes.add("Prism"); subtypes.add("Reflection"); subtypes.add("Sand"); subtypes.add("Saproling"); subtypes.add("Serf"); subtypes.add("Splinter"); subtypes.add("Survivor"); subtypes.add("Tetravite"); subtypes.add("Triskelavite"); } catch (SQLException ex) { } return subtypes; } public CardInfo findCard(String setCode, int cardNumber) { try { QueryBuilder queryBuilder = cardDao.queryBuilder(); queryBuilder.where().eq("setCode", new SelectArg(setCode)).and().eq("cardNumber", cardNumber).and().eq("nightCard", false); List result = cardDao.query(queryBuilder.prepare()); if (!result.isEmpty()) { return result.get(0); } } catch (SQLException ex) { } return null; } public List getClassNames() { List names = new ArrayList<>(); try { List results = cardDao.queryForAll(); for (CardInfo card : results) { names.add(card.getClassName()); } } catch (SQLException ex) { } return names; } public List getMissingCards(List classNames) { try { QueryBuilder queryBuilder = cardDao.queryBuilder(); queryBuilder.where().not().in("className", classNames); return cardDao.query(queryBuilder.prepare()); } catch (SQLException ex) { } return new ArrayList<>(); } /** * * @param name * @return random card with the provided name or null if none is found */ public CardInfo findCard(String name) { List cards = findCards(name); if (!cards.isEmpty()) { return cards.get(random.nextInt(cards.size())); } return null; } public List findCards(String name) { try { QueryBuilder queryBuilder = cardDao.queryBuilder(); queryBuilder.where().eq("name", new SelectArg(name)); return cardDao.query(queryBuilder.prepare()); } catch (SQLException ex) { } return new ArrayList<>(); } public List findCards(CardCriteria criteria) { try { QueryBuilder queryBuilder = cardDao.queryBuilder(); criteria.buildQuery(queryBuilder); return cardDao.query(queryBuilder.prepare()); } catch (SQLException ex) { } return new ArrayList<>(); } public long getContentVersionFromDB() { try { ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL); return RepositoryUtil.getDatabaseVersion(connectionSource, VERSION_ENTITY_NAME + "Content"); } catch (SQLException ex) { ex.printStackTrace(); } return 0; } public void setContentVersion(long version) { try { ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL); RepositoryUtil.updateVersion(connectionSource, VERSION_ENTITY_NAME + "Content", version); } catch (SQLException ex) { ex.printStackTrace(); } } public long getContentVersionConstant() { return CARD_CONTENT_VERSION; } public void closeDB() { try { if (cardDao != null && cardDao.getConnectionSource() != null) { DatabaseConnection conn = cardDao.getConnectionSource().getReadWriteConnection(); conn.executeStatement("shutdown compact", 0); } } catch (SQLException ex) { } } }