biz.gabrys.maven.plugins.css.splitter.tree.OrderedTree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of css-splitter-maven-plugin
Show all versions of css-splitter-maven-plugin
Splits CSS stylesheets to smaller files ("parts") which contain maximum X rules.
/*
* 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;
}
}
}