All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.gradle.internal.ImmutableActionSet Maven / Gradle / Ivy
/*
* Copyright 2017 the original author or authors.
*
* 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 org.gradle.internal;
import com.google.common.collect.ImmutableSet;
import org.gradle.api.Action;
/**
* An immutable composite {@link Action} implementation which has set semantics. Optimized for high execute to mutate ratio, and for a small number of actions.
*
* This set also INTENTIONALLY ignores {@link Actions#doNothing()} actions and empty sets as to avoid growing for something that would never do anything.
*
* Actions are executed in order of insertion. Duplicates are ignored. Execution stops on the first failure.
*
* Implements {@link InternalListener} as components themselves should be decorated if appropriate.
*
* @param the type of the subject of the action
*/
public abstract class ImmutableActionSet implements Action, InternalListener {
private static final int FEW_VALUES = 5;
private static final ImmutableActionSet EMPTY = new EmptySet();
/**
* Creates an empty action set.
*/
public static ImmutableActionSet empty() {
return Cast.uncheckedNonnullCast(EMPTY);
}
/**
* Creates an action set.
*/
public static ImmutableActionSet of(Action... actions) {
if (actions.length == 0) {
return empty();
}
ImmutableSet.Builder> builder = ImmutableSet.builder();
for (Action action : actions) {
if (action == Actions.DO_NOTHING || (action instanceof EmptySet)) {
continue;
}
unpackAction(action, builder);
}
ImmutableSet> set = builder.build();
return fromActions(set);
}
private static void unpackAction(Action action, ImmutableSet.Builder> builder) {
if (action instanceof ImmutableActionSet) {
ImmutableActionSet immutableSet = Cast.uncheckedNonnullCast(action);
immutableSet.unpackInto(builder);
} else {
builder.add(action);
}
}
protected abstract void unpackInto(ImmutableSet.Builder> builder);
/**
* Creates a new set that runs the actions of this set plus the given action.
*/
public ImmutableActionSet add(Action action) {
if (action == Actions.DO_NOTHING || action instanceof EmptySet || action == this) {
return this;
}
if (action instanceof SingletonSet) {
SingletonSet singletonSet = Cast.uncheckedNonnullCast(action);
return addOne(singletonSet.singleAction);
}
if (action instanceof SetWithFewActions) {
SetWithFewActions compositeSet = Cast.uncheckedNonnullCast(action);
return addAll(compositeSet);
}
if (action instanceof SetWithManyActions) {
SetWithManyActions compositeSet = Cast.uncheckedNonnullCast(action);
return addAll(compositeSet);
}
return addOne(action);
}
private static ImmutableActionSet plus(ImmutableActionSet one, ImmutableActionSet two) {
ImmutableSet.Builder> builder = ImmutableSet.builder();
one.unpackInto(builder);
two.unpackInto(builder);
ImmutableSet> set = builder.build();
return fromActions(set);
}
private static ImmutableActionSet plus(ImmutableActionSet one, Action two) {
ImmutableSet.Builder> builder = ImmutableSet.builder();
one.unpackInto(builder);
builder.add(two);
ImmutableSet> set = builder.build();
return fromActions(set);
}
private static ImmutableActionSet fromActions(ImmutableSet> set) {
if (set.isEmpty()) {
return empty();
}
if (set.size() == 1) {
return new SingletonSet(set.iterator().next());
}
if (set.size() <= FEW_VALUES) {
return new SetWithFewActions(set);
}
return new SetWithManyActions(set);
}
/**
* Creates a new set that includes the actions from this set plus the actions from the given set.
*/
public ImmutableActionSet mergeFrom(ImmutableActionSet sibling) {
if (sibling == this) {
return this;
}
if (sibling.isEmpty()) {
return this;
}
if (isEmpty()) {
return Cast.uncheckedNonnullCast(sibling);
}
return add(sibling);
}
/**
* Does this set do anything?
*/
public abstract boolean isEmpty();
abstract ImmutableActionSet addAll(SetWithFewActions source);
abstract ImmutableActionSet addAll(SetWithManyActions source);
abstract ImmutableActionSet addOne(Action action);
private static class EmptySet extends ImmutableActionSet {
@Override
ImmutableActionSet addOne(Action action) {
return new SingletonSet(action);
}
@Override
ImmutableActionSet addAll(SetWithManyActions source) {
return source;
}
@Override
ImmutableActionSet addAll(SetWithFewActions source) {
return source;
}
@Override
protected void unpackInto(ImmutableSet.Builder> builder) {
}
@Override
public void execute(Object o) {
}
@Override
public boolean isEmpty() {
return true;
}
}
private static class SingletonSet extends ImmutableActionSet {
private final Action singleAction;
SingletonSet(Action singleAction) {
this.singleAction = singleAction;
}
@Override
ImmutableActionSet addOne(Action action) {
if (action.equals(singleAction)) {
return this;
}
return new SetWithFewActions(Cast.[]>uncheckedNonnullCast(new Action[]{singleAction, action}));
}
@Override
ImmutableActionSet addAll(SetWithFewActions source) {
if (singleAction.equals(source.actions[0])) {
// Already at the front. If not at the front, need to recreate
return source;
}
if (source.actions.length < FEW_VALUES && !source.contains(singleAction)) {
// Adding a small set with no duplicates
Action[] newActions = Cast.uncheckedNonnullCast(new Action[source.actions.length + 1]);
newActions[0] = singleAction;
System.arraycopy(source.actions, 0, newActions, 1, source.actions.length);
return new SetWithFewActions(newActions);
}
return plus(this, source);
}
@Override
ImmutableActionSet addAll(SetWithManyActions source) {
return plus(this, source);
}
@Override
protected void unpackInto(ImmutableSet.Builder> builder) {
builder.add(singleAction);
}
@Override
public void execute(T t) {
singleAction.execute(t);
}
@Override
public boolean isEmpty() {
return false;
}
}
private static class SetWithFewActions extends ImmutableActionSet {
private final Action[] actions;
SetWithFewActions(ImmutableSet> set) {
actions = Cast.uncheckedNonnullCast(set.toArray(new Action[set.size()]));
}
SetWithFewActions(Action[] actions) {
this.actions = actions;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
ImmutableActionSet addOne(Action action) {
if (contains(action)) {
// Duplicate, ignore
return this;
}
if (actions.length < FEW_VALUES) {
// Adding an action that is not a duplicate
Action[] newActions = Cast.uncheckedNonnullCast(new Action[actions.length + 1]);
System.arraycopy(actions, 0, newActions, 0, actions.length);
newActions[actions.length] = action;
return new SetWithFewActions(newActions);
}
return plus(this, action);
}
@Override
ImmutableActionSet addAll(SetWithFewActions source) {
return plus(this, source);
}
@Override
ImmutableActionSet addAll(SetWithManyActions source) {
return plus(this, source);
}
@Override
protected void unpackInto(ImmutableSet.Builder> builder) {
builder.add(actions);
}
@Override
public void execute(T t) {
for (Action action : actions) {
action.execute(t);
}
}
public boolean contains(Action action) {
for (Action current : actions) {
if (current.equals(action)) {
return true;
}
}
return false;
}
}
private static class SetWithManyActions extends ImmutableActionSet {
private final ImmutableSet> multipleActions;
SetWithManyActions(ImmutableSet> multipleActions) {
this.multipleActions = multipleActions;
}
@Override
ImmutableActionSet addOne(Action action) {
return plus(this, action);
}
@Override
ImmutableActionSet addAll(SetWithManyActions source) {
return plus(this, source);
}
@Override
ImmutableActionSet addAll(SetWithFewActions source) {
return plus(this, source);
}
@Override
protected void unpackInto(ImmutableSet.Builder> builder) {
builder.addAll(multipleActions);
}
@Override
public void execute(T t) {
for (Action action : multipleActions) {
action.execute(t);
}
}
@Override
public boolean isEmpty() {
return false;
}
}
}