/**
 * Mapping Datastore Blueprints Implementation :
 * provide a Mapping DS domain, repository and service blueprints implementation
 * Copyright (C) 2013  Mathilde Ffrench
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.echinopsii.ariane.community.core.mapping.ds.blueprintsimpl.repository;

import net.echinopsii.ariane.community.core.mapping.ds.blueprintsimpl.cache.MappingDSCacheEntity;
import net.echinopsii.ariane.community.core.mapping.ds.blueprintsimpl.graphdb.MappingDSGraphDB;
import net.echinopsii.ariane.community.core.mapping.ds.blueprintsimpl.domain.EndpointImpl;
import net.echinopsii.ariane.community.core.mapping.ds.blueprintsimpl.domain.NodeImpl;
import net.echinopsii.ariane.community.core.mapping.ds.repository.NodeRepo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.Set;

public class NodeRepoImpl implements NodeRepo<NodeImpl> {

    private final static Logger log = LoggerFactory.getLogger(NodeRepoImpl.class);

    public static Set<NodeImpl> getRepository() {
        return MappingDSGraphDB.getNodes();
    }

    @Override
    public NodeImpl saveNode(NodeImpl node) {
        MappingDSGraphDB.saveVertexEntity(node);
        log.debug("Added node {} to graph({}).", new Object[]{node.toString(), MappingDSGraphDB.getVertexMaxCursor()});
        return node;
    }

    @Override
    public void deleteNode(NodeImpl node) {
        for (NodeImpl childNode : node.getNodeChildNodes()) {
            this.deleteNode(childNode);
        }

        Set<EndpointImpl> clonedESet = new HashSet<>(node.getNodeEndpoints());
        for (EndpointImpl endpoint : clonedESet) {
            log.debug("Deleted endpoint {} from graph({}).", new Object[]{endpoint.getEndpointURL(), MappingDSGraphDB.getVertexMaxCursor()});
            node.removeEndpoint(endpoint);
        }

        for (NodeImpl twinNode : node.getTwinNodes()) {
            twinNode.removeTwinNode(node);
        }

        if (node.getNodeParentNode() != null) {
            node.getNodeParentNode().removeNodeChildNode(node);
        }

        if (node.getNodeDepth() == 1) {
            node.getNodeContainer().removeContainerNode(node);
        }

        MappingDSGraphDB.deleteEntity(node);
        log.debug("Deleted node {} and all its linked entities from graph({}).", new Object[]{node.toString(), MappingDSGraphDB.getVertexMaxCursor()});
    }

    @Override
    public NodeImpl findNodeByID(long ID) {
        NodeImpl ret = null;
        MappingDSCacheEntity entity = MappingDSGraphDB.getVertexEntity(ID);
        if (entity != null) {
            if (entity instanceof NodeImpl) {
                ret = (NodeImpl) entity;
            } else {
                log.error("CONSISTENCY ERROR : entity {} is not a node.", entity.getElement().getId());
            }
        }
        return ret;
    }

    @Override
    public NodeImpl findNodeByEndpointURL(String URL) {
        NodeImpl ret = null;
        EndpointImpl ep = MappingDSGraphDB.getIndexedEndpoint(URL);
        if (ep != null) {
            ret = ep.getEndpointParentNode();
        }
        return ret;
    }

    @Override
    public Set<NodeImpl> findNodesByProperties(String key, Object value) {
        return MappingDSGraphDB.getNodes(key, value);
    }
}
@@ -1294,24 +1294,92 @@
 n.NodeImpl;%0A
+import net.echinopsii.ariane.community.core.mapping.ds.domain.Node;%0A
 import net.e
@@ -1496,24 +1496,52 @@
 erFactory;%0A%0A
+import java.util.ArrayList;%0A
 import java.
@@ -1554,16 +1554,39 @@
 ashSet;%0A
+import java.util.List;%0A
 import j
@@ -2167,29 +2167,28 @@
         
-for (
+Set%3C
 NodeImpl
  childNo
@@ -2179,16 +2179,17 @@
 NodeImpl
+%3E
  childNo
@@ -2186,27 +2186,58 @@
 l%3E childNode
- : 
+sToRemove = new HashSet%3CNodeImpl%3E(
 node.getNode
@@ -2241,34 +2241,33 @@
 odeChildNodes())
- %7B
+;
 %0A            thi
@@ -2259,19 +2259,61 @@
         
-   
+for (NodeImpl childNode : childNodesToRemove)
  this.de
@@ -2333,33 +2333,59 @@
 dNode);%0A        
-%7D
+childNodesToRemove.clear();
 %0A%0A        Set%3CEn
@@ -2695,25 +2695,24 @@
       %7D%0A
-%0A
         
 for (Nod
@@ -2703,29 +2703,57 @@
         
-for (
+clonedESet.clear();%0A%0A        Set%3C
 NodeImpl
  twinNod
@@ -2744,16 +2744,17 @@
 NodeImpl
+%3E
  twinNod
@@ -2754,19 +2754,50 @@
 twinNode
- : 
+sToRemove = new HashSet%3CNodeImpl%3E(
 node.get
@@ -2808,18 +2808,17 @@
 Nodes())
- %7B
+;
 %0A       
@@ -2818,19 +2818,59 @@
         
-   
+for (NodeImpl twinNode : twinNodesToRemove)
  twinNod
@@ -2893,33 +2893,58 @@
 (node);%0A        
-%7D
+twinNodesToRemove.clear();
 %0A%0A        if (no
@@ -2974,30 +2974,16 @@
 != null)
- %7B%0A           
  node.ge
@@ -3022,34 +3022,24 @@
 dNode(node);
-%0A        %7D
 %0A%0A        if
@@ -3065,30 +3065,16 @@
 () == 1)
- %7B%0A           
  node.ge
@@ -3116,26 +3116,16 @@
 e(node);
-%0A        %7D
 %0A%0A      

remove concurrent access exception possibilities on node repo