/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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 org.junit.Assert;
import org.junit.Test;
import org.onosproject.store.service.DocumentPath;
import org.onosproject.store.service.DocumentTree;
import org.onosproject.store.service.IllegalDocumentModificationException;
import org.onosproject.store.service.NoSuchDocumentPathException;
import org.onosproject.store.service.Versioned;

/**
 * Tests for {@code DefaultDocumentTree}.
 */
public class DefaultDocumentTreeTest {

    @Test
    public void testTreeConstructor() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        Assert.assertEquals(tree.root(), path("root"));
    }

    @Test
    public void testCreateNodeAtRoot() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        Assert.assertTrue(tree.create(path("root.a"), "bar"));
        Assert.assertFalse(tree.create(path("root.a"), "baz"));
    }

    @Test
    public void testCreateNodeAtNonRoot() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        Assert.assertTrue(tree.create(path("root.a.b"), "baz"));
    }

    @Test
    public void testCreateRecursive() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.createRecursive(path("root.a.b.c"), "bar");
        Assert.assertEquals(tree.get(path("root.a.b.c")).value(), "bar");
        Assert.assertNull(tree.get(path("root.a.b")).value());
        Assert.assertNull(tree.get(path("root.a")).value());
    }

    @Test(expected = IllegalDocumentModificationException.class)
    public void testCreateRecursiveRoot() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.createRecursive(path("root"), "bar");;
    }

    @Test(expected = IllegalDocumentModificationException.class)
    public void testCreateNodeFailure() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a.b"), "bar");
    }

    @Test
    public void testGetRootValue() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        tree.create(path("root.a.b"), "baz");
        Versioned<String> root = tree.get(path("root"));
        Assert.assertNotNull(root);
        Assert.assertNull(root.value());
    }

    @Test
    public void testGetInnerNode() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        tree.create(path("root.a.b"), "baz");
        Versioned<String> nodeValue = tree.get(path("root.a"));
        Assert.assertNotNull(nodeValue);
        Assert.assertEquals("bar", nodeValue.value());
    }

    @Test
    public void testGetLeafNode() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        tree.create(path("root.a.b"), "baz");
        Versioned<String> nodeValue = tree.get(path("root.a.b"));
        Assert.assertNotNull(nodeValue);
        Assert.assertEquals("baz", nodeValue.value());
    }

    @Test
    public void getMissingNode() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        tree.create(path("root.a.b"), "baz");
        Assert.assertNull(tree.get(path("root.x")));
        Assert.assertNull(tree.get(path("root.a.x")));
        Assert.assertNull(tree.get(path("root.a.b.x")));
    }

    @Test
    public void testGetChildren() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        tree.create(path("root.a.b"), "alpha");
        tree.create(path("root.a.c"), "beta");
        Assert.assertEquals(2, tree.getChildren(path("root.a")).size());
        Assert.assertEquals(0, tree.getChildren(path("root.a.b")).size());
    }

    @Test(expected = NoSuchDocumentPathException.class)
    public void testGetChildrenFailure() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        tree.getChildren(path("root.a.b"));
    }

    @Test(expected = IllegalDocumentModificationException.class)
    public void testSetRootFailure() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.set(tree.root(), "bar");
    }

    @Test
    public void testSet() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        Assert.assertNull(tree.set(path("root.a.b"), "alpha"));
        Assert.assertEquals("alpha", tree.set(path("root.a.b"), "beta").value());
        Assert.assertEquals("beta", tree.get(path("root.a.b")).value());
    }

    @Test(expected = IllegalDocumentModificationException.class)
    public void testSetInvalidNode() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.set(path("root.a.b"), "alpha");
    }

    public void testReplaceWithVersion() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        tree.create(path("root.a.b"), "alpha");
        Versioned<String> value = tree.get(path("root.a.b"));
        Assert.assertTrue(tree.replace(path("root.a.b"), "beta", value.version()));
        Assert.assertFalse(tree.replace(path("root.a.b"), "beta", value.version()));
        Assert.assertFalse(tree.replace(path("root.x"), "beta", 1));
    }

    public void testReplaceWithValue() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        tree.create(path("root.a.b"), "alpha");
        Assert.assertTrue(tree.replace(path("root.a.b"), "beta", "alpha"));
        Assert.assertFalse(tree.replace(path("root.a.b"), "beta", "alpha"));
        Assert.assertFalse(tree.replace(path("root.x"), "beta", "bar"));
        Assert.assertTrue(tree.replace(path("root.x"), "beta", null));
    }

    @Test(expected = IllegalDocumentModificationException.class)
    public void testRemoveRoot() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.removeNode(tree.root());
    }

    @Test
    public void testRemove() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.create(path("root.a"), "bar");
        tree.create(path("root.a.b"), "alpha");
        Assert.assertEquals("alpha", tree.removeNode(path("root.a.b")).value());
        Assert.assertEquals(0, tree.getChildren(path("root.a")).size());
    }

    @Test(expected = NoSuchDocumentPathException.class)
    public void testRemoveInvalidNode() {
        DocumentTree<String> tree = new DefaultDocumentTree<>();
        tree.removeNode(path("root.a"));
    }

    private static DocumentPath path(String path) {
        return DocumentPath.from(path);
    }
}

@@ -2364,17 +2364,16 @@
  %22bar%22);
-;
 %0A    %7D%0A%0A

Fix checkstyle error