package de.saring.exerciseviewer.parser;
import de.saring.exerciseviewer.core.EVException;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
/**
* This factory will always returns the proper ExerciseParser implementation
* for the specified filename. This factory uses the singleton pattern.
* <p/>
* New parsers can be added just by implementing the ExerciseParser interfaces
* and registering them in the META-INF/service directory. New parsers must not
* be part of the SportsTracker-Jar, the parser-Jar just needs to be added to
* the application classpath.
* <p/>
* The parsers can also be implemented as Groovy scripts, but these needs to be
* compiled to class-Files too. It would also be possible to run the Groovy
* parsers without compile using the GroovyClassLoader, but the disadvantages
* are slower performance and no syntax check via the compiler.
*
* @author Stefan Saring
* @version 2.0
*/
public class ExerciseParserFactory {
/**
* The singleton instance.
*/
private static ExerciseParserFactory instance;
/**
* The ServiceLoader instance for all ExerciseParser implementations.
*/
private final ServiceLoader<ExerciseParser> exerciseParserLoader;
/**
* Creates a new instance of ExerciseParserFactory and loads all
* ExerciseParser implementations available in the classpath.
*/
private ExerciseParserFactory() {
exerciseParserLoader = ServiceLoader.load(ExerciseParser.class);
}
/**
* Returns the instance of the appropriate exercise parser for the specified
* exercise filename. The proper parser will be assigned by using the
* filename suffix.
*
* @param filename name of the exercise file to parse
* @return instance of the appropriate exercise parser
* @throws EVException when no proper parser has been found
*/
public static ExerciseParser getParser(String filename) throws EVException {
createInstance();
// return the parser implementation which matches the filename suffix
for (ExerciseParser parser : instance.exerciseParserLoader) {
for (String suffix : parser.getInfo().getSuffixes()) {
if (filename.endsWith("." + suffix)) {
return parser;
}
}
}
throw new EVException("No parser has been found for filename '" + filename + "' ...");
}
/**
* Returns the list of all ExerciseParserInfo objects for all available parser
* implementations (useful e.g. for File Open dialogs for list of suffixes).
*
* @return list of ExerciseParserInfo objects for all parser implementations
*/
public static List<ExerciseParserInfo> getExerciseParserInfos() {
createInstance();
List<ExerciseParserInfo> lInfos = new ArrayList<>();
for (ExerciseParser parser : instance.exerciseParserLoader) {
lInfos.add(parser.getInfo());
}
return lInfos;
}
/**
* Creates the singleton instance of the factory when not done yet.
*/
private static synchronized void createInstance() {
if (instance == null) {
instance = new ExerciseParserFactory();
}
}
}