com.swirlds.common.merkle.impl.PartialNaryMerkleInternal Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swirlds-common Show documentation
Show all versions of swirlds-common Show documentation
Swirlds is a software platform designed to build fully-distributed applications that harness the power of the cloud without servers. Now you can develop applications with fairness in decision making, speed, trust and reliability, at a fraction of the cost of traditional server-based platforms.
/*
* Copyright (C) 2016-2024 Hedera Hashgraph, LLC
*
* 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.swirlds.common.merkle.impl;
import com.swirlds.common.merkle.MerkleInternal;
import com.swirlds.common.merkle.MerkleNode;
import com.swirlds.common.merkle.exceptions.IllegalChildIndexException;
import com.swirlds.common.merkle.impl.internal.AbstractMerkleInternal;
import java.util.ArrayList;
import java.util.List;
/**
* This class implements boilerplate functionality for an N-Ary {@link MerkleInternal}
* (i.e. an internal node with a variable number of children > 2). Classes that implement {@link MerkleInternal}
* are not required to extend a class such as this or {@link PartialBinaryMerkleInternal}, but absent
* a reason it is recommended to do so in order to avoid re-implementation of this code.
*/
public non-sealed class PartialNaryMerkleInternal extends AbstractMerkleInternal implements PartialMerkleInternal {
private final ArrayList children;
public PartialNaryMerkleInternal() {
children = new ArrayList<>(Math.min(MIN_CHILD_COUNT, getMinimumChildCount()));
}
/**
* Classes that inherit from AbstractMerkleLeaf are required to call super() in their constructors.
*
* @param initialSize
* Indicates the number of children links to be initially created, can be resized, but that is slow,
* so it is far better to pick the right size from the outset if you can.
*/
protected PartialNaryMerkleInternal(final int initialSize) {
if (initialSize > MAX_CHILD_COUNT_UBOUND) {
throw new IllegalChildIndexException(MIN_CHILD_COUNT, MAX_CHILD_COUNT_UBOUND, initialSize);
}
children = new ArrayList<>(initialSize);
}
/**
* Copy constructor.
*/
protected PartialNaryMerkleInternal(final PartialNaryMerkleInternal that) {
super(that);
children = new ArrayList<>(that.getNumberOfChildren());
}
/**
* {@inheritDoc}
*
* Return the current number of children for this node. Some or all can be null.
*/
@Override
public int getNumberOfChildren() {
return children.size();
}
/**
* {@inheritDoc}
*
* @param index
* The position to look for a child.
* @param
* the type of the child
* @return The child found at that position.
*/
@SuppressWarnings("unchecked")
@Override
public T getChild(final int index) {
if (children.size() <= index || index < 0) {
checkChildIndexIsValid(index);
return null;
}
return (T) children.get(index);
}
/**
* {@inheritDoc}
*
* Select a child using an index number. This will throw an error if an illegal value is used.
*
* @param index
* which child position is going to be updated
* @param child
* replacement merkle node for that position
*/
@Override
protected void setChildInternal(final int index, final MerkleNode child) {
children.set(index, child);
}
/**
* @param index
* expand the array of children to include index
*/
@Override
protected void allocateSpaceForChild(final int index) {
for (int i = children.size(); i <= index; i++) {
children.add(null);
}
}
/**
* {@inheritDoc}
*
* @param children
* this is an array of children to be added
* @param version
* serialization version (specifying format to be used)
*
* Can't make this final because PTT overrides it
*/
@Override
public void addDeserializedChildren(final List children, final int version) {
for (final MerkleNode child : this.children) {
if (child != null) {
child.release();
}
}
this.children.clear();
super.addDeserializedChildren(children, version);
}
/**
* check whether the requested index is in valid range [0, maximum child count),
* if not throw an {@link IllegalChildIndexException}
*
* @param index
* requested index of a child
*/
@Override
protected void checkChildIndexIsValid(final int index) {
int maxSize = Math.min(getMaximumChildCount(), MAX_CHILD_COUNT_UBOUND);
// note, if the maxSize is 0 this will always throw
if (index < 0 || index >= maxSize) {
throw new IllegalChildIndexException(0, maxSize - 1, index);
}
}
}