/*
* 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.teradata.tempto;
import com.google.common.collect.ImmutableSet;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static com.google.common.collect.ImmutableSet.copyOf;
import static com.google.common.collect.Lists.transform;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.Arrays.asList;
/**
* An utility class for composing requirements.
*/
public final class Requirements
{
public static CompositeRequirement compose(Requirement... requirements)
{
return compose(asList(requirements));
}
public static CompositeRequirement compose(List<Requirement> requirements)
{
return new MultiCompositeRequirement(ImmutableSet.of(copyOf(wrapAsCompositeRequirements(requirements))));
}
public static CompositeRequirement allOf(Requirement... requirements)
{
return allOf(asList(requirements));
}
public static CompositeRequirement allOf(List<Requirement> requirements)
{
return new MultiCompositeRequirement(copyOf(transform(wrapAsCompositeRequirements(requirements), ImmutableSet::<CompositeRequirement>of)));
}
private static List<CompositeRequirement> wrapAsCompositeRequirements(List<Requirement> requirements)
{
return transform(requirements, (Requirement requirement) -> {
if (requirement instanceof CompositeRequirement) {
return (CompositeRequirement) requirement;
}
else {
return new SingletonCompositeRequirement(requirement);
}
});
}
private static class SingletonCompositeRequirement
implements CompositeRequirement
{
private final Set<Set<Requirement>> requirementsSets;
public SingletonCompositeRequirement(Requirement requirement)
{
this.requirementsSets = ImmutableSet.of(ImmutableSet.of(requirement));
}
public Set<Set<Requirement>> getRequirementsSets()
{
return requirementsSets;
}
}
private static class MultiCompositeRequirement
implements CompositeRequirement
{
private final Set<Set<CompositeRequirement>> requirementsSetsBranches;
public MultiCompositeRequirement(Set<Set<CompositeRequirement>> requirementsSetsBranches)
{
this.requirementsSetsBranches = requirementsSetsBranches;
}
@Override
public Set<Set<Requirement>> getRequirementsSets()
{
Set<Set<Requirement>> expandedRequirementsSets = newHashSet();
for (Set<CompositeRequirement> requirementsSetsBranch : requirementsSetsBranches) {
expandedRequirementsSets.addAll(expandRequirements(requirementsSetsBranch));
}
return expandedRequirementsSets;
}
private Set<Set<Requirement>> expandRequirements(Collection<CompositeRequirement> requirementsSetsBranch)
{
Set<Set<Requirement>> expandedRequirementsSets = ImmutableSet.of(ImmutableSet.of());
for (CompositeRequirement requirementsSets : requirementsSetsBranch) {
expandedRequirementsSets = expandRequirements(expandedRequirementsSets, requirementsSets);
}
return expandedRequirementsSets;
}
private Set<Set<Requirement>> expandRequirements(Set<Set<Requirement>> expandedRequirementsSets, CompositeRequirement requirementsSets)
{
Set<Set<Requirement>> newExpandedRequirementsSets = newHashSet();
for (Set<Requirement> expandedRequirementSet : expandedRequirementsSets) {
for (Set<Requirement> requirementSet : requirementsSets.getRequirementsSets()) {
Set<Requirement> newExpandedRequirementSet = ImmutableSet.<Requirement>builder()
.addAll(expandedRequirementSet)
.addAll(requirementSet)
.build();
newExpandedRequirementsSets.add(newExpandedRequirementSet);
}
}
return newExpandedRequirementsSets;
}
}
private Requirements()
{
}
}