Newer
Older
KeeperJerry_Launcher / Launcher / source / hasher / FileNameMatcher.java
package launcher.hasher;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.regex.Pattern;

import launcher.LauncherAPI;
import launcher.helper.IOHelper;

public final class FileNameMatcher {
	private static final Entry[] NO_ENTRIES = new Entry[0];

	// Instance
	private final Entry[] update;
	private final Entry[] verify;
	private final Entry[] exclusions;

	@LauncherAPI
	public FileNameMatcher(String[] update, String[] verify, String[] exclusions) {
		this.update = toEntries(update);
		this.verify = toEntries(verify);
		this.exclusions = toEntries(exclusions);
	}

	private FileNameMatcher(Entry[] update, Entry[] verify, Entry[] exclusions) {
		this.update = update;
		this.verify = verify;
		this.exclusions = exclusions;
	}

	@LauncherAPI
	public boolean shouldUpdate(Collection<String> path) {
		return (anyMatch(update, path) || anyMatch(verify, path)) && !anyMatch(exclusions, path);
	}

	@LauncherAPI
	public boolean shouldVerify(Collection<String> path) {
		return anyMatch(verify, path) && !anyMatch(exclusions, path);
	}

	@LauncherAPI
	public FileNameMatcher verifyOnly() {
		return new FileNameMatcher(NO_ENTRIES, verify, exclusions);
	}

	private static boolean anyMatch(Entry[] entries, Collection<String> path) {
		return Arrays.stream(entries).anyMatch(e -> e.matches(path));
	}

	private static Entry[] toEntries(String... entries) {
		return Arrays.stream(entries).map(Entry::new).toArray(Entry[]::new);
	}

	private static final class Entry {
		private static final Pattern SPLITTER = Pattern.compile(Pattern.quote(IOHelper.CROSS_SEPARATOR) + '+');
		private final Pattern[] parts;

		private Entry(CharSequence exclusion) {
			parts = SPLITTER.splitAsStream(exclusion).map(Pattern::compile).toArray(Pattern[]::new);
		}

		private boolean matches(Collection<String> path) {
			if (parts.length > path.size()) {
				return false;
			}

			// Verify path parts
			Iterator<String> iterator = path.iterator();
			for (Pattern patternPart : parts) {
				String pathPart = iterator.next();
				if (!patternPart.matcher(pathPart).matches()) {
					return false;
				}
			}

			// All matches
			return true;
		}
	}
}