package water.parser; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; /** * Service to manage optional implementation of parsers. */ public final class ParserService { public static ParserService INSTANCE = new ParserService(); /** Service loader. * * Based on JavaDoc of SPI: "Instances of this class are not safe for use by multiple concurrent threads." - all usages of the loader * are protected by synchronized block. */ private final ServiceLoader<ParserProvider> loader; public ParserService() { loader = ServiceLoader.load(ParserProvider.class); } /** Return list of all parser providers sorted based on priority. */ public List<ParserProvider> getAllProviders() { return getAllProviders(true); } /** * Returns all parser providers sorted based on priority if required. * * @param sort * @return */ synchronized public List<ParserProvider> getAllProviders(boolean sort) { List<ParserProvider> providers = new ArrayList<>(); for(ParserProvider pp : loader) { providers.add(pp); } if (sort) { Collections.sort(providers, PARSER_PROVIDER_COMPARATOR); } return providers; } synchronized public String[] getAllProviderNames(boolean sort) { List<ParserProvider> providers = getAllProviders(sort); String[] names = new String[providers.size()]; int i = 0; for (ParserProvider pp : providers) { names[i++] = pp.info().name(); } return names; } public ParserProvider getByInfo(ParserInfo info) { return getByName(info.name()); } synchronized public ParserProvider getByName(String name) { for (ParserProvider pp : loader) { if (pp.info().name().equals(name)) { return pp; } } return null; } private static Comparator<ParserProvider> PARSER_PROVIDER_COMPARATOR = new Comparator<ParserProvider>() { @Override public int compare(ParserProvider o1, ParserProvider o2) { int x = o1.info().prior; int y = o2.info().prior; // Cannot use Integer.compare(int, int) since it is available from Java7 and also cannot // use `-` for comparison return (x < y) ? -1 : ((x == y) ? 0 : 1); } }; }