-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #214 from strangelookingnerd/feature/list_availabl…
…e_icons Provide Java implementation to list available icons
- Loading branch information
Showing
2 changed files
with
177 additions
and
0 deletions.
There are no files selected for viewing
111 changes: 111 additions & 0 deletions
111
src/main/java/io/jenkins/plugins/fontawesome/FontAwesomeIcons.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package io.jenkins.plugins.fontawesome; | ||
|
||
import edu.umd.cs.findbugs.annotations.CheckForNull; | ||
import org.apache.commons.lang3.StringUtils; | ||
|
||
import java.io.IOException; | ||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.net.URL; | ||
import java.nio.file.*; | ||
import java.util.*; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
import java.util.stream.Stream; | ||
|
||
/** | ||
* Utility to work with icons provided by the font-awesome-api-plugin. | ||
* | ||
* @author strangelookingnerd | ||
*/ | ||
public final class FontAwesomeIcons { | ||
|
||
private static final Logger LOGGER = Logger.getLogger(FontAwesomeIcons.class.getName()); | ||
private static final String SVG_FILE_ENDING = ".svg"; | ||
private static final String IMAGES_SYMBOLS_PATH = "images/symbols/"; | ||
private static final String FONT_AWESOME_API_PLUGIN = "font-awesome-api"; | ||
private static final String ICON_CLASS_NAME_PATTERN = "symbol-%s plugin-" + FONT_AWESOME_API_PLUGIN; | ||
|
||
/** | ||
* Takes an icon name and generates an icon class name from it. | ||
* | ||
* @param icon the icon name | ||
* @return the icon class name | ||
*/ | ||
public static String getIconClassName(final String icon) { | ||
return String.format(ICON_CLASS_NAME_PATTERN, icon); | ||
} | ||
|
||
/** | ||
* Get all available icons provided by the font-awesome-api-plugin. | ||
* | ||
* @return a sorted map of available icons with icon name as key and the icon | ||
* class name as value. | ||
*/ | ||
public static Map<String, String> getAvailableIcons() { | ||
return getAvailableIcons(null); | ||
} | ||
|
||
/** | ||
* Get all available icons provided by the font-awesome-api-plugin filtered by their style. | ||
* | ||
* @param filter the style to filter | ||
* @return a sorted map of available icons with icon name as key and the icon | ||
* class name as value filtered by the given style. | ||
*/ | ||
public static Map<String, String> getAvailableIcons(final SvgTag.FontAwesomeStyle filter) { | ||
return getIconsFromClasspath(filter); | ||
} | ||
|
||
private static Map<String, String> getIconsFromClasspath(final SvgTag.FontAwesomeStyle filter) { | ||
try { | ||
Enumeration<URL> urls = FontAwesomeIcons.class.getClassLoader().getResources(IMAGES_SYMBOLS_PATH); | ||
|
||
while (urls.hasMoreElements()) { | ||
URL url = urls.nextElement(); | ||
|
||
if (StringUtils.contains(url.toExternalForm(), FONT_AWESOME_API_PLUGIN)) { | ||
URI uri = url.toURI(); | ||
|
||
if (StringUtils.equals(uri.getScheme(), "jar")) { | ||
try (FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap())) { | ||
return collectIcons(fileSystem.getPath(IMAGES_SYMBOLS_PATH), filter); | ||
} | ||
} | ||
else { | ||
return collectIcons(Paths.get(uri), filter); | ||
} | ||
} | ||
} | ||
} | ||
catch (IOException | URISyntaxException ex) { | ||
LOGGER.log(Level.WARNING, "Unable to read available icons: Resource unavailable.", ex); | ||
} | ||
|
||
return new LinkedHashMap<>(); | ||
} | ||
|
||
private static Map<String, String> collectIcons(final Path path, @CheckForNull final SvgTag.FontAwesomeStyle filter) throws IOException { | ||
Map<String, String> icons = new LinkedHashMap<>(); | ||
|
||
if (path != null) { | ||
try (Stream<Path> stream = filter == null ? Files.walk(path, 2) : Files.walk(path.resolve(filter.name().toLowerCase(Locale.ENGLISH)), 1)) { | ||
stream.filter(icon -> icon != null && icon.getFileName() != null && StringUtils.endsWith(icon.getFileName().toString(), SVG_FILE_ENDING)) | ||
.sorted().forEach(icon -> { | ||
if (icon.getParent() != null && icon.getParent().getFileName() != null && icon.getFileName() != null) { | ||
String iconName = icon.getParent().getFileName() + "/" + StringUtils.removeEnd(icon.getFileName().toString(), SVG_FILE_ENDING); | ||
icons.put(iconName, getIconClassName(iconName)); | ||
} | ||
} | ||
); | ||
} | ||
} | ||
|
||
return icons; | ||
} | ||
|
||
private FontAwesomeIcons() { | ||
// hidden | ||
} | ||
|
||
} |
66 changes: 66 additions & 0 deletions
66
src/test/java/io/jenkins/plugins/fontawesome/FontAwesomeIconsTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package io.jenkins.plugins.fontawesome; | ||
|
||
import org.apache.commons.lang3.StringUtils; | ||
import org.junit.jupiter.api.BeforeAll; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.EnumSource; | ||
import org.junit.jupiter.params.provider.NullSource; | ||
|
||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.Locale; | ||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
/** | ||
* Test Class for {@link FontAwesomeIcons}. | ||
* | ||
* @author strangelookingnerd | ||
*/ | ||
class FontAwesomeIconsTest { | ||
|
||
@BeforeAll | ||
static void init() { | ||
assertThat( | ||
Files.exists(Paths.get("./target/classes/images/symbols/"))) | ||
.as("No Font Awesome Symbols found! Try running 'mvn process-resources' first!") | ||
.isTrue(); | ||
} | ||
|
||
@Test | ||
void testGetIconClassName() { | ||
assertThat(FontAwesomeIcons.getIconClassName("test")).isEqualTo("symbol-test plugin-font-awesome-api"); | ||
} | ||
|
||
@ParameterizedTest | ||
@NullSource | ||
@EnumSource(SvgTag.FontAwesomeStyle.class) | ||
void testGetAvailableIconsFiltered(final SvgTag.FontAwesomeStyle style) throws Exception { | ||
Map<String, String> availableIcons = style == null ? FontAwesomeIcons.getAvailableIcons() : FontAwesomeIcons.getAvailableIcons(style); | ||
|
||
assertThat(availableIcons).isNotNull().isNotEmpty(); | ||
|
||
try (Stream<Path> stream = Files | ||
.walk(Paths.get("./target/classes/images/symbols/" + (style == null ? "" : style.name().toLowerCase(Locale.ENGLISH))), 2)) { | ||
|
||
Set<String> iconNames = stream | ||
.filter(path -> StringUtils.endsWith(path.getFileName().toString(), ".svg")) | ||
.map(path -> path.getParent().getFileName().toString() + "/" + StringUtils.removeEnd(path.getFileName().toString(), ".svg")) | ||
.collect(Collectors.toSet()); | ||
|
||
assertThat(availableIcons.keySet()).isEqualTo(iconNames); | ||
|
||
for (Entry<String, String> icon : availableIcons.entrySet()) { | ||
assertThat(FontAwesomeIcons.getIconClassName(icon.getKey())).isEqualTo(icon.getValue()); | ||
} | ||
} | ||
} | ||
|
||
} |