Skip to content

Commit

Permalink
Merge pull request #214 from strangelookingnerd/feature/list_availabl…
Browse files Browse the repository at this point in the history
…e_icons

Provide Java implementation to list available icons
  • Loading branch information
uhafner committed Jul 16, 2023
2 parents a89a03a + a419909 commit bc015f1
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 0 deletions.
111 changes: 111 additions & 0 deletions src/main/java/io/jenkins/plugins/fontawesome/FontAwesomeIcons.java
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
}

}
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());
}
}
}

}

0 comments on commit bc015f1

Please sign in to comment.