/*
 * Copyright 2015-2016 the original author or authors.
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution and is available at
 *
 * http://www.eclipse.org/legal/epl-v10.html
 */

package org.junit.gen5.launcher;

import static java.util.Arrays.asList;
import static org.junit.gen5.commons.meta.API.Usage.Experimental;

import java.util.List;
import java.util.stream.Stream;

import org.junit.gen5.commons.meta.API;
import org.junit.gen5.engine.FilterResult;
import org.junit.gen5.engine.TestDescriptor;
import org.junit.gen5.engine.TestTag;

/**
 * Factory methods for creating {@link PostDiscoveryFilter PostDiscoveryFilters}
 * based on <em>require</em> and <em>exclude</em> tags.
 *
 * @since 5.0
 */
@API(Experimental)
public final class TagFilter {

	private TagFilter() {
		/* no-op */
	}

	/**
	 * Create a <em>require</em> filter based on the supplied {@code tags}.
	 *
	 * <p>Containers and tests will only be executed if they are tagged with
	 * at least one of the supplied <em>require</em> tags.
	 */
	public static PostDiscoveryFilter requireTags(String... tags) {
		return requireTags(asList(tags));
	}

	/**
	 * Create a <em>require</em> filter based on the supplied {@code tags}.
	 *
	 * <p>Containers and tests will only be executed if they are tagged with
	 * at least one of the supplied <em>require</em> tags.
	 */
	public static PostDiscoveryFilter requireTags(List<String> tags) {
		return descriptor -> FilterResult.includedIf(trimmedTagsOf(descriptor).anyMatch(tags::contains));
	}

	/**
	 * Create an <em>exclude</em> filter based on the supplied {@code tags}.
	 *
	 * <p>Containers and tests will only be executed if they are <em>not</em>
	 * tagged with any of the supplied <em>exclude</em> tags.
	 */
	public static PostDiscoveryFilter excludeTags(String... tags) {
		return excludeTags(asList(tags));
	}

	/**
	 * Create an <em>exclude</em> filter based on the supplied {@code tags}.
	 *
	 * <p>Containers and tests will only be executed if they are <em>not</em>
	 * tagged with any of the supplied <em>exclude</em> tags.
	 */
	public static PostDiscoveryFilter excludeTags(List<String> tags) {
		return descriptor -> FilterResult.includedIf(trimmedTagsOf(descriptor).noneMatch(tags::contains));
	}

	private static Stream<String> trimmedTagsOf(TestDescriptor descriptor) {
		// @formatter:off
		return descriptor.getTags().stream()
				.map(TestTag::getName)
				.map(String::trim);
		// @formatter:on
	}

}

@@ -543,16 +543,66 @@
 ta.API;%0A
+import org.junit.gen5.commons.util.Preconditions;%0A
 import o
@@ -1178,32 +1178,99 @@
 uire%3C/em%3E tags.%0A
+%09 *%0A%09 * @param tags the required tags; never %7B@code null%7D or empty%0A
 %09 */%0A%09public sta
@@ -1315,32 +1315,88 @@
 ring... tags) %7B%0A
+%09%09Preconditions.notNull(tags, %22tags must not be null%22);%0A
 %09%09return require
@@ -1623,32 +1623,98 @@
 uire%3C/em%3E tags.%0A
+%09 *%0A%09 * @param tags the require tags; never %7B@code null%7D or empty%0A
 %09 */%0A%09public sta
@@ -1762,32 +1762,98 @@
 String%3E tags) %7B%0A
+%09%09Preconditions.notEmpty(tags, %22tags must not be null or empty%22);%0A
 %09%09return descrip
@@ -2149,32 +2149,98 @@
 lude%3C/em%3E tags.%0A
+%09 *%0A%09 * @param tags the exclude tags; never %7B@code null%7D or empty%0A
 %09 */%0A%09public sta
@@ -2285,32 +2285,88 @@
 ring... tags) %7B%0A
+%09%09Preconditions.notNull(tags, %22tags must not be null%22);%0A
 %09%09return exclude
@@ -2606,16 +2606,82 @@
 %3E tags.%0A
+%09 *%0A%09 * @param tags the exclude tags; never %7B@code null%7D or empty%0A
 %09 */%0A%09pu
@@ -2745,16 +2745,82 @@
 tags) %7B%0A
+%09%09Preconditions.notEmpty(tags, %22tags must not be null or empty%22);%0A
 %09%09return

Add missing preconditions to TagFilter