package managers.nodes;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.List;
import managers.functions.SuccessFunction;
import managers.relationships.RelManager;
import models.nodes.LabeledNodeWithProperties;
import neo4play.NodeService;
import play.libs.F.Function;
import play.libs.F.Promise;
import play.libs.WS;


public abstract class LabeledNodeManager extends NodeManager {

    protected String label;

    public Promise<Boolean> exists(JsonNode properties) {
        return exists(this.label, properties);
    }

    protected Promise<Boolean> exists(JsonNode properties, String idField) {
        final ObjectNode props = (ObjectNode) properties.deepCopy();
        return exists(this.label, props.retain(idField));
    }

    protected Promise<Boolean> create(JsonNode properties, String location) {
        Promise<WS.Response> response =
            NodeService.createNode(this.label, properties, location);
        return response.map(new SuccessFunction());
    }

    protected Promise<Boolean> create(
        final JsonNode properties, final String location, String idField) {
        Promise<Boolean> exists = exists(properties, idField);
        Promise<Boolean> created = exists.flatMap(
            new Function<Boolean, Promise<Boolean>>() {
                public Promise<Boolean> apply(Boolean exists) {
                    if (exists) {
                        return Promise.pure(false);
                    }
                    Promise<WS.Response> response = NodeService.createNode(
                        LabeledNodeManager.this.label, properties, location);
                    return response.map(new SuccessFunction());
                }
            });
        return created;
    }

    public Promise<Boolean> update(
        JsonNode oldProperties, JsonNode newProperties) {
        return update(this.label, oldProperties, newProperties);
    }

    public Promise<Boolean> update(
        JsonNode oldProperties, JsonNode newProperties, String location) {
        return update(this.label, oldProperties, newProperties, location);
    }

    protected Promise<Boolean> delete(JsonNode properties, String location) {
        Promise<WS.Response> response =
            NodeService.deleteNode(this.label, properties, location);
        return response.map(new SuccessFunction());
    }

    protected Promise<Boolean> orphaned(
        LabeledNodeWithProperties node, RelManager relManager) {
        Promise<List<JsonNode>> incomingRelationships =
            relManager.to(node);
        return incomingRelationships.map(
            new Function<List<JsonNode>, Boolean>() {
                public Boolean apply(List<JsonNode> incomingRelationships) {
                    return incomingRelationships.size() == 0;
                }
            });
    }

}

@@ -478,16 +478,29 @@
 label;%0A%0A
+    // READ%0A%0A
     publ
@@ -541,32 +541,32 @@
 e properties) %7B%0A
-
         return e
@@ -806,32 +806,47 @@
 Field));%0A    %7D%0A%0A
+    // CREATE%0A%0A
     protected Pr
@@ -1808,32 +1808,47 @@
 created;%0A    %7D%0A%0A
+    // UPDATE%0A%0A
     public Promi
@@ -2182,32 +2182,47 @@
 cation);%0A    %7D%0A%0A
+    // DELETE%0A%0A
     protected Pr
@@ -2437,39 +2437,74 @@
 essFunction());%0A
-
     %7D%0A%0A
+    // Connections to other nodes%0A%0A
     protected Pr

Enable operations that write to the DB to be rolled back on error by wrapping them in transactions.