diff options
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.java | 170 |
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(); + } + } +} |