package org.hedgecode.chess.scanner;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
+import org.hedgecode.chess.scanner.entity.PGNGame;
import org.hedgecode.chess.scanner.portal.ChessBombScanner;
import org.hedgecode.chess.scanner.portal.ChessGamesScanner;
import org.hedgecode.chess.scanner.portal.LiChessScanner;
*/
public final class ChessHogScanner {
- private static ChessHogScanner _instance;
+ private static ChessHogScanner singleton;
- private final Map<ScannerType, Scanner> SCANNERS = new HashMap<ScannerType, Scanner>() {
+ private final Map<ScannerType, Scanner> scanners = new HashMap<ScannerType, Scanner>() {
{
put( ScannerType.CHESSGAMES, new ChessGamesScanner() );
put( ScannerType.LICHESS, new LiChessScanner() );
}
};
- public static Scanner get(ScannerType type) {
- return getInstance().scanner(type);
+ private final Set<ScannerType> initScanners = new HashSet<>();
+
+ /**
+ * Get Scanner by {@code ScannerType}.
+ *
+ * @param type Scanner type (binding to specific chess portal).
+ * @return Implementation of {@code Scanner} for specific portal.
+ */
+ public static Scanner scanner(ScannerType type) {
+ return getStore().getScanner(type);
+ }
+
+ /**
+ * Scan PGN game by URL (for all scanner types).
+ *
+ * @param url URL string for scan.
+ * @return PGN game.
+ * @throws ChessHogScannerException Incorrect URL or unknown chess portal.
+ */
+ public static PGNGame scan(String url) throws ChessHogScannerException {
+ String hostName;
+ try {
+ hostName = new URL(url).getHost();
+ } catch (MalformedURLException cause) {
+ throw new ChessHogScannerException(
+ String.format("Incorrect URL: %s", url), cause
+ );
+ }
+ ScannerType type = ScannerType.byHost(hostName);
+ if (type == null) {
+ throw new ChessHogScannerException(
+ String.format("Host %s is not among the known for the scanner", hostName)
+ );
+ }
+ return scanner(type).scanUrl(url);
}
private void init() {
+ for (ScannerType type : scanners.keySet()) {
+ init(type);
+ }
+ }
+
+ private void init(ScannerType type) {
+ Scanner scanner = scanners.get(type);
try {
- for (Scanner scanner : SCANNERS.values()) {
- if (scanner instanceof Initiable) {
- Initiable initiableScanner = (Initiable) scanner;
- initiableScanner.init();
- }
+ if (scanner instanceof Initiable) {
+ Initiable initiableScanner = (Initiable) scanner;
+ initiableScanner.init();
}
+ initScanners.add(type);
} catch (ChessHogScannerException e) {
throw new RuntimeException(e);
}
}
- private Scanner scanner(ScannerType type) {
- return SCANNERS.get(type);
+
+ private Scanner getScanner(ScannerType type) {
+ if (!initScanners.contains(type)) {
+ init(type);
+ }
+ return scanners.get(type);
}
private ChessHogScanner() {
+ if (!ChessHogScannerProperties.is("scanner.lazy.init")) {
+ init();
+ }
}
- private static ChessHogScanner getInstance() {
- if (_instance == null) {
- _instance = new ChessHogScanner();
- _instance.init();
+ private static ChessHogScanner getStore() {
+ if (singleton == null) {
+ singleton = new ChessHogScanner();
}
- return _instance;
+ return singleton;
}
}
}
private static void copyright() {
- int inceptionYear = Integer.parseInt(
- ChessHogScannerProperties.get("scanner.inception.year")
- );
+ int inceptionYear = ChessHogScannerProperties.getInt("scanner.inception.year");
int currentYear = Calendar.getInstance().get(Calendar.YEAR);
String copyright = currentYear > inceptionYear
? String.format("%s-%s %s", inceptionYear, currentYear, COPYRIGHT)
public static final String CRLF = System.getProperty("line.separator");
- public static final String PORTAL_CHESSGAMES = "chessgames";
- public static final String PORTAL_LICHESS = "lichess";
- public static final String PORTAL_CHESSBOMB = "chessbomb";
- public static final String PORTAL_CHESS24 = "chess24";
- public static final String PORTAL_CHESSCOM = "chesscom";
+ public static final String TYPE_CHESSGAMES = "chessgames";
+ public static final String TYPE_LICHESS = "lichess";
+ public static final String TYPE_CHESSBOMB = "chessbomb";
+ public static final String TYPE_CHESS24 = "chess24";
+ public static final String TYPE_CHESSCOM = "chesscom";
+
+ public static final String DOMAIN_CHESSGAMES = "chessgames.com";
+ public static final String DOMAIN_LICHESS = "lichess.org";
+ public static final String DOMAIN_CHESSBOMB = "www.chessbomb.com";
+ public static final String DOMAIN_CHESS24 = "chess24.com";
+ public static final String DOMAIN_CHESSCOM = "chess.com";
public static final String PROXY_UNDEFINED = "undefined";
public static final String PROXY_HTTP = "http";
private ChessHogScannerConstants() {
throw new AssertionError(
- String.format("No %s instances!", ChessHogScannerConstants.class.getName())
+ String.format("No %s instances!", getClass().getName())
);
}
private static final String EMPTY = "";
/**
- * Gets property value.
+ * Gets string property value.
*
* @param key Property key.
* @return Property value (possibly empty string, but never {@code null}).
}
/**
+ * Gets boolean property value.
+ *
+ * @param key Property key.
+ * @return Property value ({@code false} by default).
+ */
+ public static boolean is(String key) {
+ return Boolean.parseBoolean(
+ PROPERTIES.getProperty(key, Boolean.FALSE.toString())
+ );
+ }
+
+ /**
+ * Zero integer for not found properties.
+ */
+ private static final String ZERO = "0";
+
+ /**
+ * Gets integer property value.
+ *
+ * @param key Property key.
+ * @return Property value ({@code 0} by default).
+ */
+ public static int getInt(String key) {
+ return Integer.parseInt(
+ PROPERTIES.getProperty(key, ZERO)
+ );
+ }
+
+ /**
* Private constructor.
*/
private ChessHogScannerProperties() {
*/
public interface Scanner {
- PGNTournament getTournament(String tournamentId) throws ChessHogScannerException;
+ PGNTournament scanTournament(String tournamentId) throws ChessHogScannerException;
PGNTournament findTournament(String tournamentName) throws ChessHogScannerException;
- PGNGame getGame(String gameId) throws ChessHogScannerException;
+ PGNGame scanGame(String gameId) throws ChessHogScannerException;
- PGNGame getGame(String gameId, String tournamentId) throws ChessHogScannerException;
+ PGNGame scanGame(String gameId, String tournamentId) throws ChessHogScannerException;
+
+ PGNGame scanUrl(String gameUrl) throws ChessHogScannerException;
}
package org.hedgecode.chess.scanner;
+import static org.hedgecode.chess.scanner.ChessHogScannerConstants.*;
+
/**
* ScannerType
*
*/
public enum ScannerType {
- CHESSGAMES (ChessHogScannerConstants.PORTAL_CHESSGAMES),
- LICHESS (ChessHogScannerConstants.PORTAL_LICHESS),
- CHESSBOMB (ChessHogScannerConstants.PORTAL_CHESSBOMB),
- CHESS24 (ChessHogScannerConstants.PORTAL_CHESS24),
- CHESSCOM (ChessHogScannerConstants.PORTAL_CHESSCOM);
+ CHESSGAMES ( TYPE_CHESSGAMES, DOMAIN_CHESSGAMES ),
+ LICHESS ( TYPE_LICHESS, DOMAIN_LICHESS ),
+ CHESSBOMB ( TYPE_CHESSBOMB, DOMAIN_CHESSBOMB ),
+ CHESS24 ( TYPE_CHESS24, DOMAIN_CHESS24 ),
+ CHESSCOM ( TYPE_CHESSCOM, DOMAIN_CHESSCOM );
private String type;
+ private String domain;
- ScannerType(String type) {
+ ScannerType(String type, String domain) {
this.type = type;
+ this.domain = domain;
}
public String type() {
return type;
}
+ public String domain() {
+ return domain;
+ }
+
public static ScannerType byType(String type) {
for (ScannerType scannerType : ScannerType.values()) {
if (scannerType.type.equals(type))
return null;
}
+ public static ScannerType byHost(String host) {
+ if (host != null) {
+ for (ScannerType scannerType : ScannerType.values()) {
+ if (host.contains(scannerType.domain))
+ return scannerType;
+ }
+ }
+ return null;
+ }
+
}
}
@Override
- public PGNTournament getTournament(String tournamentId) throws ChessHogScannerException {
+ public PGNTournament scanTournament(String tournamentId) throws ChessHogScannerException {
String decodeTournament = decodeUrlByRegex(
assignUrl(tournamentId, null),
getSettings().getTournamentGamesUrlRegex()
for (String gameId : tournamentFormat.gameUrls()) {
tournament.addGame(
- getGame(gameId, tournamentId)
+ scanGame(gameId, tournamentId)
);
}
String tournamentId = arenaFormat.findTournament(tournamentName);
return tournamentId != null
- ? getTournament(tournamentId)
+ ? scanTournament(tournamentId)
: null;
}
@Override
- public PGNGame getGame(String gameId) throws ChessHogScannerException {
+ public PGNGame scanGame(String gameId) throws ChessHogScannerException {
throw new ChessHogScannerException(
"ChessBomb does not support searching game without a tournament name!"
);
}
@Override
- public PGNGame getGame(String gameId, String tournamentId) throws ChessHogScannerException {
+ public PGNGame scanGame(String gameId, String tournamentId) throws ChessHogScannerException {
String decodeGame = decodeUrlByRegex(
assignUrl(gameId, tournamentId, true),
getSettings().getGameUrlRegex()
);
}
+ @Override
+ public PGNGame scanUrl(String gameUrl) throws ChessHogScannerException {
+ return null;
+ }
+
private String decodeUrlByRegex(String url, String regex) throws ChessHogScannerException {
String encodeString = match(
url,
}
@Override
- public PGNTournament getTournament(String tournamentId) throws ChessHogScannerException {
+ public PGNTournament scanTournament(String tournamentId) throws ChessHogScannerException {
PGNTournament tournament = new PGNTournament(tournamentId);
assignTournamentGames(tournament);
return tournament;
}
@Override
- public PGNGame getGame(String gameId) throws ChessHogScannerException {
+ public PGNGame scanGame(String gameId) throws ChessHogScannerException {
String pgn = request(
assignUrl(gameId)
);
}
@Override
- public PGNGame getGame(String gameId, String tournamentId) throws ChessHogScannerException {
- return getGame(gameId);
+ public PGNGame scanGame(String gameId, String tournamentId) throws ChessHogScannerException {
+ return scanGame(gameId);
+ }
+
+ @Override
+ public PGNGame scanUrl(String gameUrl) throws ChessHogScannerException {
+ return null;
}
private void assignTournamentGames(PGNTournament tournament) throws ChessHogScannerException {
for (String gameId : gamesId) {
tournament.addGame(
- getGame(gameId)
+ scanGame(gameId)
);
}
}
}
@Override
- public PGNTournament getTournament(String tournamentId) throws ChessHogScannerException {
+ public PGNTournament scanTournament(String tournamentId) throws ChessHogScannerException {
PGNTournament tournament = new PGNTournament(tournamentId);
assignTournamentGames(tournament);
return tournament;
}
@Override
- public PGNGame getGame(String gameId) throws ChessHogScannerException {
+ public PGNGame scanGame(String gameId) throws ChessHogScannerException {
String pgn = request(
assignUrl(gameId)
);
}
@Override
- public PGNGame getGame(String gameId, String tournamentId) throws ChessHogScannerException {
- return getGame(gameId);
+ public PGNGame scanGame(String gameId, String tournamentId) throws ChessHogScannerException {
+ return scanGame(gameId);
+ }
+
+ @Override
+ public PGNGame scanUrl(String gameUrl) throws ChessHogScannerException {
+ return null;
}
private void assignTournamentGames(PGNTournament tournament) throws ChessHogScannerException {
scanner.version=0.1-SNAPSHOT
scanner.inception.year=2019
+scanner.lazy.init=true
+
scanner.use.proxy=false
scanner.proxy.server=
scanner.proxy.auth=