All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.spricom.dessert.slicing.AbstractSlice Maven / Gradle / Ivy

package de.spricom.dessert.slicing;

/*-
 * #%L
 * Dessert Dependency Assertion Library for Java
 * %%
 * Copyright (C) 2017 - 2023 Hans Jörg Heßmann
 * %%
 * 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.
 * #L%
 */

import de.spricom.dessert.matching.NamePattern;
import de.spricom.dessert.util.Predicate;

import java.util.*;

/**
 * Defines convenience methods available to all {@link Slice} implementations.
 */
public abstract class AbstractSlice implements Slice {

    AbstractSlice() {
    }

    @Override
    public Slice plus(Iterable slices) {
        List list = new LinkedList();
        list.add(this);
        for (Slice slice : slices) {
            list.add(slice);
        }
        if (list.size() == 1) {
            return list.get(0);
        }
        return new UnionSlice(list);
    }

    @Override
    public Slice plus(Slice... slices) {
        if (slices.length == 0) {
            return this;
        }
        List list = new ArrayList(slices.length + 1);
        list.add(this);
        list.addAll(Arrays.asList(slices));
        return new UnionSlice(list);
    }

    @Override
    public Slice minus(Iterable slices) {
        final Slice union = Slices.of(slices);
        Predicate excluded = new Predicate() {

            @Override
            public boolean test(Clazz clazz) {
                return !union.contains(clazz);
            }
        };
        return slice(excluded);
    }

    @Override
    public Slice minus(Slice... slices) {
        return minus(Arrays.asList(slices));
    }

    @Override
    public Slice minus(String pattern) {
        return this.minus(this.slice(pattern));
    }

    @Override
    public Slice minus(Predicate predicate) {
        return this.minus(this.slice(predicate));
    }

    @Override
    public Slice slice(Iterable slices) {
        List list = new LinkedList();
        for (Slice slice : slices) {
            list.add(slice);
        }
        if (list.isEmpty()) {
            return this;
        }
        final Slice union = list.size() == 1 ? list.get(0) : new UnionSlice(list);
        Predicate isInUnion = new Predicate() {
            @Override
            public boolean test(Clazz clazz) {
                return union.contains(clazz);
            }
        };
        return slice(isInUnion);
    }

    @Override
    public Slice slice(Slice... slices) {
        return slice(Arrays.asList(slices));
    }

    @Override
    public Slice slice(String pattern) {
        final NamePattern namePattern = NamePattern.of(pattern);
        return slice(new Predicate() {

            @Override
            public boolean test(Clazz clazz) {
                return namePattern.matches(clazz.getName());
            }
        });
    }

    @Override
    public Slice dependencyClosure(Slice within) {
        Slice result = this.slice(within);
        int count;
        do {
            count = result.getClazzes().size();
            result = result.plus(result.getDependencies()).slice(within);
        } while (result.getClazzes().size() != count);
        return result;
    }

    @Override
    public ConcreteSlice getDependencies() {
        Set dependencies = new HashSet();
        for (Clazz clazz : getClazzes()) {
            dependencies.addAll(clazz.getDependencies().getClazzes());
        }
        return new ConcreteSlice(dependencies);
    }

    @Override
    public boolean uses(Slice other) {
        if (this == other) {
            return false;
        }
        for (Clazz clazz : getClazzes()) {
            for (Clazz dependency : clazz.getDependencies().getClazzes()) {
                for (Clazz alternative : dependency.getAlternatives()) {
                    if (other.contains(alternative)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    @Override
    public Slice named(String name) {
        return new NamedSlice(this, name);
    }

    @Override
    public SortedMap partitionByPackage() {
        return partitionBy(PackageSlice.partitioner(), PackageSlice.factory());
    }

    @Override
    public SortedMap partitionBy(SlicePartitioner partitioner) {
        return partitionBy(
                partitioner,
                new PartitionSliceFactory() {
                    @Override
                    public PartitionSlice createPartSlice(String partKey, Set entries, Map slices) {
                        return new PartitionSlice(partKey, entries);
                    }
                });
    }

    @Override
    public  SortedMap partitionBy(SlicePartitioner partitioner, PartitionSliceFactory partitionSliceFactory) {
        Map> split = new HashMap>();
        for (Clazz clazz : getClazzes()) {
            String key = partitioner.partKey(clazz);
            if (key != null) {
                Set matches = split.get(key);
                if (matches == null) {
                    matches = new HashSet();
                    split.put(key, matches);
                }
                matches.add(clazz);
            }
        }
        SortedMap slices = new TreeMap();
        for (Map.Entry> matches : split.entrySet()) {
            slices.put(matches.getKey(), partitionSliceFactory.createPartSlice(matches.getKey(), matches.getValue(), slices));
        }
        return slices;
    }
}