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

biz.gabrys.maven.plugins.css.splitter.tree.OrderedTree Maven / Gradle / Ivy

Go to download

Splits CSS stylesheets to smaller files ("parts") which contain maximum X rules.

There is a newer version: 2.0.3
Show newest version
/*
 * CSS Splitter Maven Plugin
 * http://css-splitter-maven-plugin.projects.gabrys.biz/
 *
 * Copyright (c) 2015 Adam Gabryś
 *
 * This file is licensed under the BSD 3-Clause (the "License").
 * You may not use this file except in compliance with the License.
 * You may obtain:
 * - a copy of the License at project page
 * - a template of the License at https://opensource.org/licenses/BSD-3-Clause
 */
package biz.gabrys.maven.plugins.css.splitter.tree;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class OrderedTree implements OrderedTreeNode {

    public static final int MIN_NUMBER_OF_CHILDREN = 2;

    private final int numberOfChildren;
    private final List> children;
    private T value;
    private int order;

    public OrderedTree(final List objects, final int numberOfChildren) {
        this(numberOfChildren);

        if (objects.isEmpty()) {
            return;
        }

        // root node is a leaf, so we need to create size - 1 additional leaves
        createLeaves(objects.size() - 1);
        fillLeaves(objects);
        fillOrder(0);
    }

    private OrderedTree(final int numberOfChildren) {
        if (numberOfChildren < MIN_NUMBER_OF_CHILDREN) {
            throw new IllegalArgumentException("Number of children cannot be smaller than 2! Current value: " + numberOfChildren);
        }
        this.numberOfChildren = numberOfChildren;
        children = new ArrayList>(numberOfChildren);
    }

    public List> getChildren() {
        return new ArrayList>(children);
    }

    public boolean hasValue() {
        return value != null;
    }

    public T getValue() {
        return value;
    }

    public int getOrder() {
        return order;
    }

    public int size() {
        int size = hasValue() ? 1 : 0;
        for (final OrderedTree child : children) {
            if (!child.isLeaf()) {
                ++size;
            }
            size += child.size();
        }
        return size;
    }

    public int getDepth() {
        if (isLeaf()) {
            return 0;
        }
        int max = 0;
        for (final OrderedTree child : children) {
            final int tmp = child.getDepth();
            if (tmp > max) {
                max = tmp;
            }
        }
        return 1 + max;
    }

    private void createLeaves(final int count) {
        for (int i = 0; i < count; ++i) {
            createLeaf();
        }
    }

    private void createLeaf() {
        if (isLeaf()) {
            children.add(new OrderedTree(numberOfChildren));
            children.add(new OrderedTree(numberOfChildren));

        } else if (children.size() < numberOfChildren) {
            children.add(new OrderedTree(numberOfChildren));

        } else {
            OrderedTree node = getNotFullyFilledNode();
            if (node == null) {
                node = findNearestLeafNode();
            }
            node.createLeaf();
        }
    }

    private boolean isLeaf() {
        return children.isEmpty();
    }

    private OrderedTree getNotFullyFilledNode() {
        if (isLeaf()) {
            return null;
        }

        if (children.size() < numberOfChildren) {
            return this;
        }

        for (final OrderedTree child : children) {
            final OrderedTree node = child.getNotFullyFilledNode();
            if (node != null) {
                return node;
            }
        }
        return null;
    }

    private OrderedTree findNearestLeafNode() {
        final List> leaves = getLeavesWithDistances();
        LeafWithDistance leafWithDistance = leaves.get(0);
        OrderedTree leaf = leafWithDistance.leaf;
        int distance = leafWithDistance.distance;
        for (int i = 1; i < leaves.size(); ++i) {
            leafWithDistance = leaves.get(i);
            if (leafWithDistance.distance < distance) {
                leaf = leafWithDistance.leaf;
                distance = leafWithDistance.distance;
            }
        }
        return leaf;
    }

    private List> getLeavesWithDistances() {
        if (isLeaf()) {
            final List> leaves = new ArrayList>();
            leaves.add(new LeafWithDistance(this, 0));
            return leaves;
        }

        final List> leaves = new LinkedList>();
        for (final OrderedTree child : children) {
            for (final LeafWithDistance leafWithDistance : child.getLeavesWithDistances()) {
                leaves.add(new LeafWithDistance(leafWithDistance.leaf, leafWithDistance.distance + 1));
            }
        }
        return leaves;
    }

    private void fillLeaves(final List objects) {
        final List> leaves = getLeaves();
        if (leaves.size() != objects.size()) {
            throw new IllegalStateException(
                    String.format("Leaves quantity (%d) is other that objects quantity (%d)!", leaves.size(), objects.size()));
        }
        for (int i = 0; i < objects.size(); ++i) {
            leaves.get(i).value = objects.get(i);
        }
    }

    private List> getLeaves() {
        final List> leavesWithDistances = getLeavesWithDistances();
        final List> leaves = new ArrayList>(leavesWithDistances.size());
        for (final LeafWithDistance leafWithDistance : leavesWithDistances) {
            leaves.add(leafWithDistance.leaf);
        }
        return leaves;
    }

    private int fillOrder(final int index) {
        order = index;
        int childOrder = index;
        for (final OrderedTree child : children) {
            ++childOrder;
            childOrder = child.fillOrder(childOrder);
        }
        return childOrder;
    }

    private static final class LeafWithDistance {

        private final OrderedTree leaf;
        private final int distance;

        private LeafWithDistance(final OrderedTree leaf, final int distance) {
            this.leaf = leaf;
            this.distance = distance;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy