class MigrationManager {

	public boolean migrate(Version from, Version to) {
		logger.info("Migrating from "+from+" to "+to);
		AtomicBoolean successful = new AtomicBoolean(true);
		List<MigrationTask> matchedMigrators = new ArrayList<>();

		boolean upgrade = to.compareTo(from)>=1;
		for(MigrationTask migrator:migrators) {
			if(migrator.asOfVersion.compareTo(upgrade?from:to)>=1 && migrator.asOfVersion.compareTo(upgrade?to:from)<=0) {
				matchedMigrators.add(migrator);
			}
		}	
		matchedMigrators.sort(new Comparator<MigrationTask>() {
			@Override
			public int compare(MigrationTask o1, MigrationTask o2) {
				return (upgrade?1:-1)*o1.asOfVersion.compareTo(o2.asOfVersion);
			}
		});
		matchedMigrators.forEach(m->{
			logger.info("Running migration task "+m);
			long t1 = System.currentTimeMillis();
			try {
				if(upgrade) {
					m.runUpgradeScript();					
				} else {
					m.runDowngradeScript();
				}
				logger.info("Migration task "+m+" successfully executed in "+(System.currentTimeMillis()-t1)+"ms");
			} catch(Exception e) {
				logger.error("Error while running upgrade/downgrade script "+m, e);
				successful.set(false);
			}
		});
		return successful.get();
	}

	public  MigrationManager(GlobalContext context);

}