package liquibase.command;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.servicelocator.ServiceLocator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Manages {@link LiquibaseCommand} implementations.
*/
public class CommandFactory {
private static CommandFactory instance;
private List<LiquibaseCommand> commands;
private CommandFactory() {
Class<? extends LiquibaseCommand>[] classes;
commands = new ArrayList<LiquibaseCommand>();
try {
classes = ServiceLocator.getInstance().findClasses(LiquibaseCommand.class);
for (Class<? extends LiquibaseCommand> clazz : classes) {
register(clazz.getConstructor().newInstance());
}
} catch (Exception e) {
throw new UnexpectedLiquibaseException(e);
}
}
public static synchronized CommandFactory getInstance() {
if (instance == null) {
instance = new CommandFactory();
}
return instance;
}
public static synchronized void reset() {
instance = new CommandFactory();
}
public LiquibaseCommand getCommand(final String commandName) {
Comparator<LiquibaseCommand> commandComparator = new Comparator<LiquibaseCommand>() {
@Override
public int compare(LiquibaseCommand o1, LiquibaseCommand o2) {
return Integer.valueOf(o2.getPriority(commandName)).compareTo(o1.getPriority(commandName));
}
};
List<LiquibaseCommand> sortedCommands = new ArrayList<LiquibaseCommand>(commands);
Collections.sort(sortedCommands, commandComparator);
if (sortedCommands.size() == 0) {
throw new UnexpectedLiquibaseException("Could not find command class for "+commandName);
}
try {
LiquibaseCommand command = sortedCommands.iterator().next().getClass().newInstance();
if (command.getPriority(commandName) <= 0) {
throw new UnexpectedLiquibaseException("Could not find command class for "+commandName);
}
return command;
} catch (Exception e) {
throw new UnexpectedLiquibaseException(e);
}
}
public void register(LiquibaseCommand command) {
commands.add(command);
}
public void unregister(LiquibaseCommand command) {
commands.remove(command);
}
}