blob: 0f5d66a7587416de221b2a6a64330b1ce0e369b2 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Foundation
*
* 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 org.onosproject.store.primitives.resources.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import org.onosproject.store.service.DocumentPath;
import org.onosproject.store.service.DocumentTreeNode;
import org.onosproject.store.service.Ordering;
import org.onosproject.store.service.Versioned;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* A {@code DocumentTree} node.
*/
public class DefaultDocumentTreeNode<V> implements DocumentTreeNode<V> {
private final DocumentPath key;
private Versioned<V> value;
private final Map<String, DocumentTreeNode<V>> children;
private final Ordering ordering;
private final DocumentTreeNode<V> parent;
public DefaultDocumentTreeNode(DocumentPath key,
V value,
long version,
Ordering ordering,
DocumentTreeNode<V> parent) {
this.key = checkNotNull(key);
this.value = new Versioned<>(value, version);
this.ordering = ordering;
this.parent = parent;
switch (ordering) {
case INSERTION:
children = Maps.newLinkedHashMap();
break;
case NATURAL:
default:
children = Maps.newTreeMap();
break;
}
}
@Override
public DocumentPath path() {
return key;
}
@Override
public Versioned<V> value() {
return value;
}
@Override
public Iterator<DocumentTreeNode<V>> children() {
return ImmutableList.copyOf(children.values()).iterator();
}
@Override
public DocumentTreeNode<V> child(String name) {
return children.get(name);
}
public DocumentTreeNode<V> parent() {
return parent;
}
/**
* Adds a new child only if one does not exist with the name.
* @param name relative path name of the child node
* @param newValue new value to set
* @param newVersion new version to set
* @return previous value; can be {@code null} if no child currently exists with that relative path name.
* a non null return value indicates child already exists and no modification occurred.
*/
public Versioned<V> addChild(String name, V newValue, long newVersion) {
DefaultDocumentTreeNode<V> child = (DefaultDocumentTreeNode<V>) children.get(name);
if (child != null) {
return child.value();
}
children.put(name, new DefaultDocumentTreeNode<>(
new DocumentPath(name, path()), newValue, newVersion, ordering, this));
return null;
}
/**
* Updates the node value.
*
* @param newValue new value to set
* @param newVersion new version to set
* @return previous value
*/
public Versioned<V> update(V newValue, long newVersion) {
Versioned<V> previousValue = value;
value = new Versioned<>(newValue, newVersion);
return previousValue;
}
/**
* Removes a child node.
*
* @param name the name of child node to be removed
* @return {@code true} if the child set was modified as a result of this call, {@code false} otherwise
*/
public boolean removeChild(String name) {
return children.remove(name) != null;
}
@Override
public int hashCode() {
return Objects.hash(this.key);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof DefaultDocumentTreeNode) {
DefaultDocumentTreeNode<V> that = (DefaultDocumentTreeNode<V>) obj;
if (this.parent.equals(that.parent)) {
if (this.children.size() == that.children.size()) {
return Sets.symmetricDifference(this.children.keySet(), that.children.keySet()).isEmpty();
}
}
}
return false;
}
@Override
public String toString() {
MoreObjects.ToStringHelper helper =
MoreObjects.toStringHelper(getClass())
.add("parent", this.parent)
.add("key", this.key)
.add("value", this.value);
for (DocumentTreeNode<V> child : children.values()) {
helper = helper.add("child", "\n" + child.path().pathElements()
.get(child.path().pathElements().size() - 1) +
" : " + child.value());
}
return helper.toString();
}
}