// Path: src/main/java/pl/exsio/nestedj/config/mem/discriminator/InMemoryTreeDiscriminator.java
// public interface InMemoryTreeDiscriminator<ID extends Serializable, N extends NestedNode<ID>> {
// 
//     /**
//      * Method that decides whether a target Node belongs to the Tree or not.
//      *
//      * @param node - target Node
//      * @return true if Node belongs to the Tree, false if Node does not belong to the Tree
//      */
//     boolean applies(N node);
// }
// 
// Path: src/main/java/pl/exsio/nestedj/config/mem/identity/InMemoryNestedNodeIdentityGenerator.java
// public interface InMemoryNestedNodeIdentityGenerator<ID extends Serializable> {
// 
//     /**
//      * Generates a unique identity for InMemory repository Node insertion
//      *
//      * @return ID - newly generated unique identity
//      */
//     ID generateIdentity();
// }
// 
// Path: src/main/java/pl/exsio/nestedj/model/NestedNode.java
// public interface NestedNode<ID extends Serializable> {
// 
//     /**
//      * Standarized Field Names used internally by NestedJ.
//      * Any Java class that implements the NestedNode interface should have fields with names matching the below constants.
//      */
//     String LEFT = "treeLeft";
//     String RIGHT = "treeRight";
//     String LEVEL = "treeLevel";
//     String PARENT_ID = "parentId";
//     String ID = "id";
// 
//     /**
//      *  Should be PK if using Database.
//      *
//      * @return unique Identifier of the Entity/Object.
//      */
//     ID getId();
// 
//     /**
//      * @return Nested Set Model LEFT value
//      */
//     Long getTreeLeft();
// 
//     /**
//      * @return Nested Set Model RIGHT value
//      */
//     Long getTreeRight();
// 
//     /**
//      * @return Nested Set Model LEVEL value
//      */
//     Long getTreeLevel();
// 
//     /**
//      * Should be a FK if using Database.
//      *
//      * @return Parent Idendifier
//      */
//     ID getParentId();
// 
//     /**
//      * Sets the unique Identifier of the Entity/Object.
//      *
//      * @param id - unique Identifier of the Entity/Object.
//      */
//     void setId(ID id);
// 
//     /**
//      * Sets the Nested Set Model LEFT value
//      *
//      * @param treeLeft - Nested Set Model LEFT value
//      */
//     void setTreeLeft(Long treeLeft);
// 
//     /**
//      * Sets the Nested Set Model RIGHT value
//      *
//      * @param treeRight - Nested Set Model RIGHT value
//      */
//     void setTreeRight(Long treeRight);
// 
//     /**
//      * Sets the Nested Set Model LEVEL value
//      *
//      * @param treeLevel - Nested Set Model LEVEL value
//      */
//     void setTreeLevel(Long treeLevel);
// 
//     /**
//      * Sets the Parent Idendifier
//      *
//      * @param parent - Parent Idendifier
//      */
//     void setParentId(ID parent);
// 
// }


import pl.exsio.nestedj.config.mem.discriminator.InMemoryTreeDiscriminator;
import pl.exsio.nestedj.config.mem.identity.InMemoryNestedNodeIdentityGenerator;
import pl.exsio.nestedj.model.NestedNode;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/*
 *  The MIT License
 *
 *  Copyright (c) 2019 eXsio.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 *  documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 *  permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *  The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 *  the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 *  BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 *  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */

package pl.exsio.nestedj.config.mem;



/**
 * Configuration class that serves as a base of creating new instances of InMemory Repository.
 *
 * @param <ID> - Nested Node Identifier Class
 * @param <N>  - Nested Node Class
 */
public class InMemoryNestedNodeRepositoryConfiguration<ID extends Serializable, N extends NestedNode<ID>> {

    private final InMemoryTreeDiscriminator<ID, N> treeDiscriminator;

    private final InMemoryNestedNodeIdentityGenerator<ID> identityGenerator;

    private final Set<N> nodes = Collections.synchronizedSet(new HashSet<>());

    /**
     * Creates new InMemory Repository with empty Tree and no Tree Discriminator.
     *
     * @param identityGenerator - Identity generator used for inserting new Nodes into an InMemory Repository.
     */
    public InMemoryNestedNodeRepositoryConfiguration(InMemoryNestedNodeIdentityGenerator<ID> identityGenerator) {
        this(identityGenerator, new ArrayList<>(), null);
    }

    /**
     * Creates new InMemory Repository with a collection of Nodes and no Tree Discriminator.
     * If the Nodes do not have proper LEFT/RIGHT/LEVEL values, Tree can be initialized with NestedNodeRepository::rebuildTree() method.
     *
     * @param identityGenerator - Identity generator used for inserting new Nodes into an InMemory Repository.
     * @param nodes             - initial collection of Nodes
     */
    public InMemoryNestedNodeRepositoryConfiguration(InMemoryNestedNodeIdentityGenerator<ID> identityGenerator, Collection<N> nodes) {
// Path: src/main/java/pl/exsio/nestedj/config/mem/discriminator/InMemoryTreeDiscriminator.java
// public interface InMemoryTreeDiscriminator<ID extends Serializable, N extends NestedNode<ID>> {
// 
//     /**
//      * Method that decides whether a target Node belongs to the Tree or not.
//      *
//      * @param node - target Node
//      * @return true if Node belongs to the Tree, false if Node does not belong to the Tree
//      */
//     boolean applies(N node);
// }
// 
// Path: src/main/java/pl/exsio/nestedj/config/mem/identity/InMemoryNestedNodeIdentityGenerator.java
// public interface InMemoryNestedNodeIdentityGenerator<ID extends Serializable> {
// 
//     /**
//      * Generates a unique identity for InMemory repository Node insertion
//      *
//      * @return ID - newly generated unique identity
//      */
//     ID generateIdentity();
// }
// 
// Path: src/main/java/pl/exsio/nestedj/model/NestedNode.java
// public interface NestedNode<ID extends Serializable> {
// 
//     /**
//      * Standarized Field Names used internally by NestedJ.
//      * Any Java class that implements the NestedNode interface should have fields with names matching the below constants.
//      */
//     String LEFT = "treeLeft";
//     String RIGHT = "treeRight";
//     String LEVEL = "treeLevel";
//     String PARENT_ID = "parentId";
//     String ID = "id";
// 
//     /**
//      *  Should be PK if using Database.
//      *
//      * @return unique Identifier of the Entity/Object.
//      */
//     ID getId();
// 
//     /**
//      * @return Nested Set Model LEFT value
//      */
//     Long getTreeLeft();
// 
//     /**
//      * @return Nested Set Model RIGHT value
//      */
//     Long getTreeRight();
// 
//     /**
//      * @return Nested Set Model LEVEL value
//      */
//     Long getTreeLevel();
// 
//     /**
//      * Should be a FK if using Database.
//      *
//      * @return Parent Idendifier
//      */
//     ID getParentId();
// 
//     /**
//      * Sets the unique Identifier of the Entity/Object.
//      *
//      * @param id - unique Identifier of the Entity/Object.
//      */
//     void setId(ID id);
// 
//     /**
//      * Sets the Nested Set Model LEFT value
//      *
//      * @param treeLeft - Nested Set Model LEFT value
//      */
//     void setTreeLeft(Long treeLeft);
// 
//     /**
//      * Sets the Nested Set Model RIGHT value
//      *
//      * @param treeRight - Nested Set Model RIGHT value
//      */
//     void setTreeRight(Long treeRight);
// 
//     /**
//      * Sets the Nested Set Model LEVEL value
//      *
//      * @param treeLevel - Nested Set Model LEVEL value
//      */
//     void setTreeLevel(Long treeLevel);
// 
//     /**
//      * Sets the Parent Idendifier
//      *
//      * @param parent - Parent Idendifier
//      */
//     void setParentId(ID parent);
// 
// }


// Path: src/main/java/pl/exsio/nestedj/config/mem/InMemoryNestedNodeRepositoryConfiguration.java
import pl.exsio.nestedj.config.mem.discriminator.InMemoryTreeDiscriminator;
import pl.exsio.nestedj.config.mem.identity.InMemoryNestedNodeIdentityGenerator;
import pl.exsio.nestedj.model.NestedNode;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/*
 *  The MIT License
 *
 *  Copyright (c) 2019 eXsio.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 *  documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 *  permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *  The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 *  the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 *  BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 *  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */

package pl.exsio.nestedj.config.mem;



/**
 * Configuration class that serves as a base of creating new instances of InMemory Repository.
 *
 * @param <ID> - Nested Node Identifier Class
 * @param <N>  - Nested Node Class
 */
public class InMemoryNestedNodeRepositoryConfiguration<ID extends Serializable, N extends NestedNode<ID>> {

    private final InMemoryTreeDiscriminator<ID, N> treeDiscriminator;

    private final InMemoryNestedNodeIdentityGenerator<ID> identityGenerator;

    private final Set<N> nodes = Collections.synchronizedSet(new HashSet<>());

    /**
     * Creates new InMemory Repository with empty Tree and no Tree Discriminator.
     *
     * @param identityGenerator - Identity generator used for inserting new Nodes into an InMemory Repository.
     */
    public InMemoryNestedNodeRepositoryConfiguration(InMemoryNestedNodeIdentityGenerator<ID> identityGenerator) {
        this(identityGenerator, new ArrayList<>(), null);
    }

    /**
     * Creates new InMemory Repository with a collection of Nodes and no Tree Discriminator.
     * If the Nodes do not have proper LEFT/RIGHT/LEVEL values, Tree can be initialized with NestedNodeRepository::rebuildTree() method.
     *
     * @param identityGenerator - Identity generator used for inserting new Nodes into an InMemory Repository.
     * @param nodes             - initial collection of Nodes
     */
    public InMemoryNestedNodeRepositoryConfiguration(InMemoryNestedNodeIdentityGenerator<ID> identityGenerator, Collection<N> nodes) {
        this(identityGenerator, nodes, null);