aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/cmdline/ResolvedTargets.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/cmdline/ResolvedTargets.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/cmdline/ResolvedTargets.java170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/ResolvedTargets.java b/src/main/java/com/google/devtools/build/lib/cmdline/ResolvedTargets.java
new file mode 100644
index 0000000000..806cd61872
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/ResolvedTargets.java
@@ -0,0 +1,170 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.cmdline;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import java.util.Collection;
+import java.util.Set;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Contains the result of the target pattern evaluation. This is a specialized container class for
+ * the result of target pattern resolution. There is no restriction on the element type, but it will
+ * usually be {@code Target}.
+ */
+@Immutable
+public final class ResolvedTargets<T> {
+ private static final ResolvedTargets<?> FAILED_RESULT =
+ new ResolvedTargets<>(ImmutableSet.of(), ImmutableSet.of(), true);
+
+ private static final ResolvedTargets<?> EMPTY_RESULT =
+ new ResolvedTargets<>(ImmutableSet.of(), ImmutableSet.of(), false);
+
+ @SuppressWarnings("unchecked")
+ public static <T> ResolvedTargets<T> failed() {
+ return (ResolvedTargets<T>) FAILED_RESULT;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> ResolvedTargets<T> empty() {
+ return (ResolvedTargets<T>) EMPTY_RESULT;
+ }
+
+ public static <T> ResolvedTargets<T> of(T target) {
+ return new ResolvedTargets<>(ImmutableSet.<T>of(target), false);
+ }
+
+ private final boolean hasError;
+ private final ImmutableSet<T> targets;
+ private final ImmutableSet<T> filteredTargets;
+
+ public ResolvedTargets(Set<T> targets, Set<T> filteredTargets, boolean hasError) {
+ this.targets = ImmutableSet.copyOf(targets);
+ this.filteredTargets = ImmutableSet.copyOf(filteredTargets);
+ this.hasError = hasError;
+ }
+
+ public ResolvedTargets(Set<T> targets, boolean hasError) {
+ this.targets = ImmutableSet.copyOf(targets);
+ this.filteredTargets = ImmutableSet.of();
+ this.hasError = hasError;
+ }
+
+ public boolean hasError() {
+ return hasError;
+ }
+
+ public ImmutableSet<T> getTargets() {
+ return targets;
+ }
+
+ public ImmutableSet<T> getFilteredTargets() {
+ return filteredTargets;
+ }
+
+ /**
+ * Returns a builder using concurrent sets, as long as you don't call filter.
+ */
+ public static <T> ResolvedTargets.Builder<T> concurrentBuilder() {
+ return new ResolvedTargets.Builder<>(
+ Sets.<T>newConcurrentHashSet(),
+ Sets.<T>newConcurrentHashSet());
+ }
+
+ public static <T> ResolvedTargets.Builder<T> builder() {
+ return new ResolvedTargets.Builder<>();
+ }
+
+ public static final class Builder<T> {
+ private Set<T> targets;
+ private Set<T> filteredTargets;
+ private volatile boolean hasError = false;
+
+ private Builder() {
+ this(Sets.<T>newLinkedHashSet(), Sets.<T>newLinkedHashSet());
+ }
+
+ private Builder(Set<T> targets, Set<T> filteredTargets) {
+ this.targets = targets;
+ this.filteredTargets = filteredTargets;
+ }
+
+ public ResolvedTargets<T> build() {
+ return new ResolvedTargets<>(targets, filteredTargets, hasError);
+ }
+
+ public Builder<T> merge(ResolvedTargets<T> other) {
+ removeAll(other.filteredTargets);
+ addAll(other.targets);
+ if (other.hasError) {
+ hasError = true;
+ }
+ return this;
+ }
+
+ public Builder<T> add(T target) {
+ targets.add(target);
+ filteredTargets.remove(target);
+ return this;
+ }
+
+ public Builder<T> addAll(Collection<T> targets) {
+ this.targets.addAll(targets);
+ this.filteredTargets.removeAll(targets);
+ return this;
+ }
+
+ public void remove(T target) {
+ targets.remove(target);
+ filteredTargets.add(target);
+ }
+
+ public Builder<T> removeAll(Collection<T> targets) {
+ this.filteredTargets.addAll(targets);
+ this.targets.removeAll(targets);
+ return this;
+ }
+
+ public Builder<T> filter(Predicate<T> predicate) {
+ Set<T> oldTargets = targets;
+ targets = Sets.newLinkedHashSet();
+ for (T target : oldTargets) {
+ if (predicate.apply(target)) {
+ add(target);
+ } else {
+ remove(target);
+ }
+ }
+ return this;
+ }
+
+ public Builder<T> setError() {
+ this.hasError = true;
+ return this;
+ }
+
+ public Builder<T> mergeError(boolean hasError) {
+ this.hasError |= hasError;
+ return this;
+ }
+
+ public boolean isEmpty() {
+ return targets.isEmpty();
+ }
+ }
+}