[LIB-9] Separate chesshog-graphics module
authorgotty <gotty@hedgecode.org>
Tue, 23 Apr 2019 15:53:38 +0000 (18:53 +0300)
committergotty <gotty@hedgecode.org>
Tue, 23 Apr 2019 15:53:38 +0000 (18:53 +0300)
24 files changed:
chesshog-format/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java [deleted file]
chesshog-graphics/pom.xml [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/Diagram.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageBuilder.java with 65% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/DiagramBuilder.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/DiagramBuilder.java with 85% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/FilenameUtils.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageBuilder.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageException.java with 73% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageConstants.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageConstants.java with 93% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageException.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFilter.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageFilter.java with 67% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageFormat.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageFormat.java with 98% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageLoader.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/ImageLoader.java with 100% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/Board.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/board/Board.java with 100% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/board/BoardLoader.java with 58% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/board/SquarePair.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/board/SquarePair.java with 100% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/DefFileSystemContractor.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemContractor.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemDetector.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/JarFileSystemContractor.java [new file with mode: 0644]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/piece/PieceSet.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/piece/PieceSet.java with 100% similarity]
chesshog-graphics/src/main/java/org/hedgecode/chess/img/piece/PieceSetLoader.java [moved from chesshog-format/src/main/java/org/hedgecode/chess/img/piece/PieceSetLoader.java with 61% similarity]
chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings.properties [new file with mode: 0644]
chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings_ru.properties [new file with mode: 0644]
pom.xml

diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java b/chesshog-format/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java
deleted file mode 100644 (file)
index 4bed015..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2018-2019. Developed by Hedgecode.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.hedgecode.chess.img;
-
-import java.io.File;
-
-/**
- *
- *
- * @author Dmitry Samoshin aka gotty
- */
-public abstract class AbstractImageLoader implements ImageLoader {
-
-    protected static final File IMAGES_PATH = new File(
-            ImageLoader.class.getResource(
-                    ImageConstants.RESOURCE_ROOT_DIR + ImageConstants.RESOURCE_IMAGES_DIR
-            ).getPath()
-    );
-
-    private Type loadType;
-
-    public AbstractImageLoader() {
-        this.loadType = Type.STATELESS;
-    }
-
-    protected abstract void clear();
-
-    @Override
-    public Type loadType() {
-        return loadType;
-    }
-
-    protected void setLoadType(Type loadType) {
-        if (Type.STATELESS.equals(loadType)) {
-            clear();
-        }
-        this.loadType = loadType;
-    }
-
-}
diff --git a/chesshog-graphics/pom.xml b/chesshog-graphics/pom.xml
new file mode 100644 (file)
index 0000000..296bf2d
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ Copyright (c) 2018. Developed by Hedgecode.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.hedgecode.chess</groupId>
+        <artifactId>chesshog</artifactId>
+        <version>0.1-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>chesshog-graphics</artifactId>
+    <version>0.1-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>Hedgecode ChessHog Graphics</name>
+    <description>
+        Hedgecode ChessHog Graphics Module.
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.hedgecode.chess</groupId>
+            <artifactId>chesshog-core</artifactId>
+            <version>${chessHogVersion}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hedgecode.chess</groupId>
+            <artifactId>chesshog-format</artifactId>
+            <version>${chessHogVersion}</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/AbstractImageLoader.java
new file mode 100644 (file)
index 0000000..c9c4f04
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img;
+
+import java.awt.image.BufferedImage;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.imageio.ImageIO;
+
+import org.hedgecode.chess.img.fs.FileSystemDetector;
+import org.hedgecode.chess.img.fs.FileSystemContractor;
+
+/**
+ * Abstract common image loader with type state of saved resources.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class AbstractImageLoader implements ImageLoader {
+
+    private static final String IMAGES_DIR =
+            ImageConstants.RESOURCE_ROOT_DIR.concat(ImageConstants.RESOURCE_IMAGES_DIR);
+
+    private Type loadType;
+
+    private URI imageResourceUri;
+
+    public AbstractImageLoader() {
+        loadType = Type.STATELESS;
+        try {
+            if (FileSystemDetector.detectJar(getImageResourceUri())) {
+                loadType = Type.STATEFUL;
+            }
+        } catch (ImageException ignored) {
+        }
+    }
+
+    protected abstract void clear();
+
+    @Override
+    public Type loadType() {
+        return loadType;
+    }
+
+    protected void setLoadType(Type loadType) {
+        if (Type.STATELESS.equals(loadType)) {
+            clear();
+        }
+        this.loadType = loadType;
+    }
+
+    protected URI getImageResourceUri() throws ImageException {
+        if (imageResourceUri == null) {
+            try {
+                imageResourceUri = getClass().getResource(IMAGES_DIR).toURI();
+            } catch (URISyntaxException e) {
+                throw new ImageException("image.unable.access.resource");
+            }
+        }
+        return imageResourceUri;
+    }
+
+    protected Map<String, BufferedImage> loadImages(String imagesPath, ImageFilter filter)
+            throws ImageException
+    {
+        Map<String, BufferedImage> images = new HashMap<>();
+        try (FileSystemContractor fsc = FileSystemDetector.detect(getImageResourceUri())) {
+            try (DirectoryStream<Path> ds =
+                         Files.newDirectoryStream(
+                                 fsc.getPath(imagesPath), filter
+                         )
+            ) {
+                for (Path file : ds) {
+                    images.put(
+                            FilenameUtils.getBaseName(
+                                    file.getFileName().toString()
+                            ).toLowerCase(),
+                            ImageIO.read(
+                                    fsc.getResourceAsStream(file)
+                            )
+                    );
+                }
+            }
+        } catch (Exception e) {
+            throw new ImageException("image.unable.access.resource", e.getMessage());
+        }
+        return images;
+    }
+
+}
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018. Developed by Hedgecode.
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package org.hedgecode.chess.img;
 
 import java.awt.image.RenderedImage;
 
-import org.hedgecode.chess.position.Builder;
 import org.hedgecode.chess.position.Position;
 
 /**
@@ -26,10 +25,22 @@ import org.hedgecode.chess.position.Position;
  *
  * @author Dmitry Samoshin aka gotty
  */
-public interface ImageBuilder extends Builder {
+public class Diagram {
 
-    String build(Position position);
+    private Position position;
+    private RenderedImage image;
 
-    RenderedImage build(Position position, String boardType, String pieceType) throws ImageException;
+    Diagram(Position position, RenderedImage image) {
+        this.position = position;
+        this.image = image;
+    }
+
+    public Position getPosition() {
+        return position;
+    }
+
+    public RenderedImage getImage() {
+        return image;
+    }
 
 }
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018. Developed by Hedgecode.
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ package org.hedgecode.chess.img;
 import java.awt.Graphics;
 import java.awt.Image;
 import java.awt.image.BufferedImage;
-import java.awt.image.RenderedImage;
 import java.io.File;
 import java.io.IOException;
 import java.util.Map;
@@ -53,12 +52,7 @@ public class DiagramBuilder implements ImageBuilder {
     }
 
     @Override
-    public String build(Position position) {
-        return ""; // todo
-    }
-
-    @Override
-    public RenderedImage build(Position position, String boardType, String pieceType)
+    public Diagram build(Position position, String boardType, String pieceType)
             throws ImageException
     {
         Map<Square, ColorPiece> squares = position.getSquares();
@@ -67,19 +61,19 @@ public class DiagramBuilder implements ImageBuilder {
         PieceSet pieces = pieceSetLoader.load(pieceType);
 
         if (board == null || pieces == null) {
-            throw new ImageException("Couldn't find image resources!"); // todo: locale
+            throw new ImageException("image.unable.find.resource");
         }
 
         int squareSize = board.squareSize();
 
-        BufferedImage diagram = board.render();
-        Graphics diagramGraphics = diagram.getGraphics();
+        BufferedImage image = board.render();
+        Graphics imageGraphics = image.getGraphics();
         for (int y = 0; y < Square.getSize(); ++y) {
             for (int x = 0; x < Square.getSize(); ++x) {
                 Square square = Square.getSquare(x, Square.getSize() - (y + 1));
                 ColorPiece colorPiece = squares.get(square);
                 if (colorPiece != null) {
-                    diagramGraphics.drawImage(
+                    imageGraphics.drawImage(
                             pieces.get(colorPiece).getScaledInstance(
                                     squareSize, squareSize, Image.SCALE_SMOOTH
                             ),
@@ -90,7 +84,9 @@ public class DiagramBuilder implements ImageBuilder {
                 }
             }
         }
-        return diagram;
+        return new Diagram(
+                position, image
+        );
     }
 
     public static ImageBuilder getInstance() {
@@ -101,7 +97,9 @@ public class DiagramBuilder implements ImageBuilder {
     public static void main(String[] args) throws IOException, ImageException {
 
         ImageIO.write(
-                DiagramBuilder.getInstance().build(Positions.INITIAL.getPosition(), "test", "shade"),
+                DiagramBuilder.getInstance().build(
+                        Positions.INITIAL.getPosition(), "test", "shade"
+                ).getImage(),
                 ImageFormat.PNG.name(),
                 new File("chessboard" + "." + ImageFormat.PNG.getExt())
         );
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/FilenameUtils.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/FilenameUtils.java
new file mode 100644 (file)
index 0000000..4b6b773
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img;
+
+/**
+ * Utilities for path, file name and extension manipulation.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class FilenameUtils {
+
+    private static final String EMPTY_STRING = "";
+
+    private static final char EXTENSION_SEPARATOR = '.';
+
+    private static final char UNIX_SEPARATOR = '/';
+    private static final char WINDOWS_SEPARATOR = '\\';
+
+    private static final String PATH_COLON = ":";
+
+    private static final String JAR_SEPARATOR = ".jar!";
+
+    private static final String OS = System.getProperty("os.name").toLowerCase();
+
+    public static String getName(final String fileName) {
+        if (fileName == null) {
+            return null;
+        }
+        final int endPathIndex = Math.max(
+                fileName.lastIndexOf(UNIX_SEPARATOR),
+                fileName.lastIndexOf(WINDOWS_SEPARATOR)
+        );
+        return fileName.substring(endPathIndex + 1);
+    }
+
+    public static String getBaseName(final String fileName) {
+        return removeExtension(
+                getName(fileName)
+        );
+    }
+
+    public static String getExtension(final String fileName) {
+        if (fileName == null) {
+            return null;
+        }
+        final int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR);
+        return extensionPos < 0
+                ? EMPTY_STRING
+                : fileName.substring(extensionPos + 1);
+    }
+
+    public static String getFullPath(final String parentDir, final String... childDirs) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(parentDir);
+        if (childDirs.length > 0) {
+            for (String childDir : childDirs) {
+                sb.append(isWindows() ? WINDOWS_SEPARATOR : UNIX_SEPARATOR).append(childDir);
+            }
+        }
+        return sb.toString();
+    }
+
+    public static String fixPath(final String path) {
+        if (isWindows()) {
+            return path.startsWith(String.valueOf(UNIX_SEPARATOR))
+                    && path.contains(PATH_COLON)
+                    ? path.substring(1)
+                    : path;
+        }
+        return path;
+    }
+
+    public static String getPathFromJar(final String jarPath) {
+        final int jarEndPos = jarPath.lastIndexOf(JAR_SEPARATOR);
+        return jarEndPos < 0
+                ? EMPTY_STRING
+                : jarPath.substring(jarEndPos + JAR_SEPARATOR.length());
+    }
+
+    private static String removeExtension(final String fileName) {
+        if (fileName == null) {
+            return null;
+        }
+        final int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR);
+        return extensionPos < 0
+                ? fileName
+                : fileName.substring(0, extensionPos);
+    }
+
+    private static boolean isWindows() {
+        return (OS.contains("win"));
+    }
+
+    private FilenameUtils() {
+        throw new AssertionError(
+                "No org.hedgecode.chess.img.FilenameUtils instances!"
+        );
+    }
+
+}
 
 package org.hedgecode.chess.img;
 
+import org.hedgecode.chess.position.Position;
+
 /**
- * Image working Exception.
+ *
  *
  * @author Dmitry Samoshin aka gotty
  */
-public class ImageException extends Exception {
-
-    private String message;
-
-    public ImageException(String message) {
-        this.message = message;
-    }
+public interface ImageBuilder {
 
-    public String getMessage() {
-        return message;
-    }
+    Diagram build(Position position, String boardType, String pieceType) throws ImageException;
 
 }
@@ -32,6 +32,8 @@ public final class ImageConstants {
     public static final String DARK_SQUARE_FILENAME = "dark";
     public static final String LIGHT_SQUARE_FILENAME = "light";
 
+    public static final String LOCALE_BUNDLE_FILE = "org.hedgecode.chess.img.LocalStrings";
+
     private ImageConstants() {
         throw new AssertionError(
                 "No ImageConstants instances!"
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageException.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/ImageException.java
new file mode 100644 (file)
index 0000000..ec77467
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img;
+
+import java.util.ResourceBundle;
+
+/**
+ * Image load/build Exception.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ImageException extends Exception {
+
+    private static final ResourceBundle LOCALE_BUNDLE =
+            ResourceBundle.getBundle(ImageConstants.LOCALE_BUNDLE_FILE);
+
+    private String localeKey;
+    private String message;
+
+    ImageException(String localeKey) {
+        this.localeKey = localeKey;
+        this.message = null;
+    }
+
+    ImageException(String localeKey, String message) {
+        this.localeKey = localeKey;
+        this.message = message;
+    }
+
+    public String getLocaleKey() {
+        return localeKey;
+    }
+
+    public String getMessage() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(LOCALE_BUNDLE.getString(localeKey));
+        if (message != null)
+            sb.append(": [").append(message).append("]");
+        return sb.toString();
+    }
+
+}
 
 package org.hedgecode.chess.img;
 
-import java.io.File;
-import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
 
 /**
  *
  *
  * @author Dmitry Samoshin aka gotty
  */
-public class ImageFilter implements FilenameFilter {
+public class ImageFilter implements DirectoryStream.Filter<Path> {
 
     private static final String[] IMAGES_EXTS = ImageFormat.getAllExts();
 
@@ -39,13 +41,17 @@ public class ImageFilter implements FilenameFilter {
     }
 
     @Override
-    public boolean accept(File dir, String name) {
-        return isImageName(name) && isImageExt(name);
+    public boolean accept(Path file) throws IOException {
+        if (Files.isDirectory(file)) {
+            return false;
+        }
+        String filename = file.getFileName().toString();
+        return acceptExt(filename) && acceptName(filename);
     }
 
-    private boolean isImageName(String name) {
+    private boolean acceptName(String filename) {
         if (names != null) {
-            name = name.substring(0, name.lastIndexOf('.'));
+            String name = FilenameUtils.getBaseName(filename);
             for (String imageName : names) {
                 if (imageName.equalsIgnoreCase(name))
                     return true;
@@ -55,8 +61,8 @@ public class ImageFilter implements FilenameFilter {
         return true;
     }
 
-    private boolean isImageExt(String ext) {
-        ext = ext.substring(ext.lastIndexOf('.') + 1);
+    private boolean acceptExt(String filename) {
+        String ext = FilenameUtils.getExtension(filename);
         for (String imageExt : IMAGES_EXTS) {
             if (imageExt.equalsIgnoreCase(ext))
                 return true;
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018. Developed by Hedgecode.
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 package org.hedgecode.chess.img.board;
 
 import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.imageio.ImageIO;
-
 import org.hedgecode.chess.img.AbstractImageLoader;
+import org.hedgecode.chess.img.FilenameUtils;
 import org.hedgecode.chess.img.ImageConstants;
 import org.hedgecode.chess.img.ImageException;
 import org.hedgecode.chess.img.ImageFilter;
@@ -36,7 +33,7 @@ import org.hedgecode.chess.img.ImageFilter;
  */
 public class BoardLoader extends AbstractImageLoader {
 
-    private static final File SQUARES_PATH = new File(IMAGES_PATH, ImageConstants.RESOURCE_SQUARES_DIR);
+    private static final String SQUARES_DIR = ImageConstants.RESOURCE_SQUARES_DIR;
 
     private static final String SQUARE_DARK = ImageConstants.DARK_SQUARE_FILENAME;
     private static final String SQUARE_LIGHT = ImageConstants.LIGHT_SQUARE_FILENAME;
@@ -48,12 +45,9 @@ public class BoardLoader extends AbstractImageLoader {
     @Override
     public Board load(String name) throws ImageException {
         Board board = null;
-        SquarePair<BufferedImage> squarePair = null;
         if (Type.STATELESS.equals(loadType()) || !squareSetMap.containsKey(name)) {
-            File boardPath = new File(SQUARES_PATH, name);
-            if (boardPath.exists() && boardPath.isDirectory()) {
-                squarePair = loadSquares(name, boardPath);
-            }
+            String boardPath = FilenameUtils.getFullPath(SQUARES_DIR, name);
+            SquarePair<BufferedImage> squarePair = loadSquares(boardPath);
             if (squarePair != null) {
                 board = Board.create(squarePair);
                 if (Type.STATEFUL.equals(loadType())) {
@@ -78,29 +72,17 @@ public class BoardLoader extends AbstractImageLoader {
         squareSetMap.clear();
     }
 
-    private SquarePair<BufferedImage> loadSquares(String name, File boardPath) throws ImageException {
-        BufferedImage dark = null, light = null;
-        File[] images = boardPath.listFiles(new ImageFilter(SQUARE_NAMES));
-        if (images != null) {
-            for (File image : images) {
-                if (image.isFile()) {
-                    String filename = image.getName();
-                    try {
-                        switch (filename.substring(0, filename.lastIndexOf('.'))) {
-                            case SQUARE_DARK:
-                                dark = ImageIO.read(image);
-                                break;
-                            case SQUARE_LIGHT:
-                                light = ImageIO.read(image);
-                                break;
-                        }
-                    } catch (IOException e) {
-                        throw new ImageException(e.getMessage());  // todo: locale
-                    }
-                }
-            }
-        }
-        return (dark != null && light != null) ? SquarePair.create(dark, light) : null;
+    private SquarePair<BufferedImage> loadSquares(String boardPath) throws ImageException {
+        Map<String, BufferedImage> images =
+                loadImages(
+                        boardPath,
+                        new ImageFilter(SQUARE_NAMES)
+                );
+        BufferedImage dark = images.get(SQUARE_DARK);
+        BufferedImage light = images.get(SQUARE_LIGHT);
+        return (dark != null && light != null)
+                ? SquarePair.create(dark, light)
+                : null; // todo: ImageException
     }
 
 }
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/DefFileSystemContractor.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/DefFileSystemContractor.java
new file mode 100644 (file)
index 0000000..58e85ee
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.fs;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+import org.hedgecode.chess.img.FilenameUtils;
+
+/**
+ *
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class DefFileSystemContractor implements FileSystemContractor {
+
+    private FileSystem fileSystem;
+    private String rootPath;
+
+    DefFileSystemContractor(URI uri) {
+        fileSystem = FileSystems.getDefault();
+        rootPath = FilenameUtils.fixPath(uri.getPath());
+    }
+
+    @Override
+    public FileSystem getFileSystem() {
+        return fileSystem;
+    }
+
+    @Override
+    public Path getPath(String path) {
+        return fileSystem.getPath(rootPath, path);
+    }
+
+    @Override
+    public InputStream getResourceAsStream(Path file) throws IOException {
+        return new FileInputStream(file.toString());
+    }
+
+    @Override
+    public void close() throws Exception {
+        // do nothing
+    }
+
+}
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemContractor.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemContractor.java
new file mode 100644 (file)
index 0000000..1ca4831
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.fs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+
+/**
+ *
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface FileSystemContractor extends AutoCloseable {
+
+    FileSystem getFileSystem();
+
+    Path getPath(String path);
+
+    InputStream getResourceAsStream(Path file) throws IOException;
+
+}
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemDetector.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/FileSystemDetector.java
new file mode 100644 (file)
index 0000000..2534c4f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.fs;
+
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * File System Detector.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class FileSystemDetector {
+
+    private static final String JAR_SCHEME_NAME = "jar";
+
+    public static FileSystemContractor detect(URI uri) throws IOException {
+        if (JAR_SCHEME_NAME.equals(uri.getScheme())) {
+            return new JarFileSystemContractor(uri);
+        } else {
+            return new DefFileSystemContractor(uri);
+        }
+    }
+
+    public static boolean detectJar(URI uri) {
+        return JAR_SCHEME_NAME.equals(uri.getScheme());
+    }
+
+}
diff --git a/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/JarFileSystemContractor.java b/chesshog-graphics/src/main/java/org/hedgecode/chess/img/fs/JarFileSystemContractor.java
new file mode 100644 (file)
index 0000000..a3d403c
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018-2019. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.img.fs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.util.Collections;
+
+import org.hedgecode.chess.img.FilenameUtils;
+
+/**
+ *
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JarFileSystemContractor implements FileSystemContractor {
+
+    private FileSystem fileSystem;
+    private String rootPath;
+
+    JarFileSystemContractor(URI uri) throws IOException {
+        fileSystem = FileSystems.newFileSystem(
+                uri, Collections.<String, String>emptyMap()
+        );
+        rootPath = FilenameUtils.getPathFromJar(uri.toString());
+    }
+
+    @Override
+    public FileSystem getFileSystem() {
+        return fileSystem;
+    }
+
+    @Override
+    public Path getPath(String path) {
+        return fileSystem.getPath(rootPath, path);
+    }
+
+    @Override
+    public InputStream getResourceAsStream(Path file) throws IOException {
+        return getClass().getResourceAsStream(file.toString());
+    }
+
+    @Override
+    public void close() throws Exception {
+        fileSystem.close();
+    }
+
+}
 
 package org.hedgecode.chess.img.piece;
 
-import java.io.File;
-import java.io.IOException;
+import java.awt.image.BufferedImage;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.imageio.ImageIO;
-
 import org.hedgecode.chess.img.AbstractImageLoader;
+import org.hedgecode.chess.img.FilenameUtils;
 import org.hedgecode.chess.img.ImageConstants;
 import org.hedgecode.chess.img.ImageException;
 import org.hedgecode.chess.img.ImageFilter;
@@ -35,7 +33,7 @@ import org.hedgecode.chess.img.ImageFilter;
  */
 public class PieceSetLoader extends AbstractImageLoader {
 
-    private static final File PIECES_PATH = new File(IMAGES_PATH, ImageConstants.RESOURCE_PIECES_DIR);
+    private static final String PIECES_DIR = ImageConstants.RESOURCE_PIECES_DIR;
 
     private static final String[] PIECES_NAMES = PieceSet.getAllPieceNames();
 
@@ -43,12 +41,10 @@ public class PieceSetLoader extends AbstractImageLoader {
 
     @Override
     public PieceSet load(String name) throws ImageException {
-        PieceSet pieceSet = null;
+        PieceSet pieceSet;
         if (Type.STATELESS.equals(loadType()) || !pieceSetMap.containsKey(name)) {
-            File piecePath = new File(PIECES_PATH, name);
-            if (piecePath.exists() && piecePath.isDirectory()) {
-                pieceSet = loadPieces(piecePath);
-            }
+            String piecePath = FilenameUtils.getFullPath(PIECES_DIR, name);
+            pieceSet = loadPieces(piecePath);
             if (Type.STATEFUL.equals(loadType()) && pieceSet != null) {
                 pieceSetMap.put(name, pieceSet);
             }
@@ -70,25 +66,22 @@ public class PieceSetLoader extends AbstractImageLoader {
         pieceSetMap.clear();
     }
 
-    private PieceSet loadPieces(File piecePath) throws ImageException {
+    private PieceSet loadPieces(String piecePath) throws ImageException {
         PieceSet pieceSet = PieceSet.create();
-        File[] images = piecePath.listFiles(new ImageFilter(PIECES_NAMES));
-        if (images != null) {
-            for (File image : images) {
-                if (image.isFile()) {
-                    String filename = image.getName();
-                    try {
-                        pieceSet.add(
-                                filename.substring(0, filename.lastIndexOf('.')),
-                                ImageIO.read(image)
-                        );
-                    } catch (IOException e) {
-                        throw new ImageException(e.getMessage()); // todo: locale
-                    }
-                }
-            }
+        Map<String, BufferedImage> images =
+                loadImages(
+                        piecePath,
+                        new ImageFilter(PIECES_NAMES)
+                );
+        for (String name : PIECES_NAMES) {
+            pieceSet.add(
+                    name,
+                    images.get(name)
+            );
         }
-        return pieceSet.isFull() ? pieceSet : null;
+        return pieceSet.isFull()
+                ? pieceSet
+                : null; // todo: ImageException
     }
 
 }
diff --git a/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings.properties b/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings.properties
new file mode 100644 (file)
index 0000000..b97b5ef
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright (c) 2018-2019. Developed by Hedgecode.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Default localized string information
+# Localized for Locale en_US
+
+image.unable.access.resource=Unable to access resources of graphic module
+image.unable.find.resource=Unable to find image resources
diff --git a/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings_ru.properties b/chesshog-graphics/src/main/resources/org/hedgecode/chess/img/LocalStrings_ru.properties
new file mode 100644 (file)
index 0000000..8e821e6
--- /dev/null
@@ -0,0 +1,18 @@
+# Copyright (c) 2018-2019. Developed by Hedgecode.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Localized for Locale ru_RU
+
+image.unable.access.resource=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u0434\u043E\u0441\u0442\u0443\u043F \u043A \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043C \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043A\u043E\u0433\u043E \u043C\u043E\u0434\u0443\u043B\u044F
+image.unable.find.resource=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u043D\u0430\u0439\u0442\u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043A\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044B
diff --git a/pom.xml b/pom.xml
index 6237452..59db211 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -25,6 +25,7 @@
         <module>chesshog-core</module>
         <module>chesshog-format</module>
         <module>chesshog-uci</module>
+        <module>chesshog-graphics</module>
         <module>chesshog-hedgefish</module>
         <module>chesshog-dbetude</module>
         <module>chesshog-qrcode</module>