controllers.Rules.java Source code

Java tutorial

Introduction

Here is the source code for controllers.Rules.java

Source

// Rules.java --- Controller that handles requests for listing, obtaining information about, and operating on rules.

// Copyright (C) 2013-2015  Tim Krones

// 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 controllers;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import java.util.List;
import models.nodes.CombinationGroup;
import models.nodes.Feature;
import models.nodes.LHS;
import models.nodes.Part;
import models.nodes.RHS;
import models.nodes.Rule;
import models.nodes.Slot;
import models.nodes.Substructure;
import play.libs.F.Function;
import play.libs.F.Promise;
import play.libs.F.Tuple;
import play.libs.Json;
import play.mvc.BodyParser;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Security;
import utils.UUIDGenerator;
import views.html.browse;
import views.html.details;
import views.html.input;
import views.html.output;

public class Rules extends Controller {

    @Security.Authenticated(Secured.class)
    public static Promise<Result> browse() {
        Promise<List<Rule>> ruleList = Rule.nodes.all();
        return ruleList.map(new Function<List<Rule>, Result>() {
            public Result apply(List<Rule> ruleList) {
                return ok(browse.render(ruleList));
            }
        });
    }

    @Security.Authenticated(Secured.class)
    public static Promise<Result> details(String name) {
        ObjectNode properties = Json.newObject();
        properties.put("name", name);
        Promise<Rule> requestedRule = Rule.nodes.full(properties);
        return requestedRule.map(new Function<Rule, Result>() {
            public Result apply(Rule requestedRule) {
                return ok(details.render(requestedRule));
            }
        });
    }

    @Security.Authenticated(Secured.class)
    public static Promise<Result> similar(String name) {
        ObjectNode properties = Json.newObject();
        properties.put("name", name);
        Promise<List<Rule>> ruleList = Rule.nodes.similar(properties);
        return ruleList.map(new Function<List<Rule>, Result>() {
            public Result apply(List<Rule> ruleList) {
                return ok(browse.render(ruleList));
            }
        });
    }

    @Security.Authenticated(Secured.class)
    public static Promise<Result> input(final String name) {
        Promise<List<Feature>> globalFeatureList = Feature.nodes.all();
        ObjectNode properties = Json.newObject();
        properties.put("name", name);
        Promise<Rule> rule = Rule.nodes.get(properties);
        rule = rule.flatMap(new Function<Rule, Promise<Rule>>() {
            public Promise<Rule> apply(final Rule rule) {
                ObjectNode properties = Json.newObject();
                String uuid = UUIDGenerator.from(rule.uuid);
                properties.put("uuid", uuid);
                properties.put("ruleUUID", rule.uuid);
                Promise<LHS> lhs = LHS.nodes.get(properties);
                return lhs.map(new Function<LHS, Rule>() {
                    public Rule apply(LHS lhs) {
                        rule.lhs = lhs;
                        return rule;
                    }
                });
            }
        });
        Promise<Tuple<List<Feature>, Rule>> results = globalFeatureList.zip(rule);
        return results.map(new Function<Tuple<List<Feature>, Rule>, Result>() {
            public Result apply(Tuple<List<Feature>, Rule> results) {
                return ok(input.render(results._1, results._2));
            }
        });
    }

    @Security.Authenticated(Secured.class)
    public static Promise<Result> output(final String name) {
        Promise<List<Part>> globalPartsList = Part.nodes.all();
        ObjectNode properties = Json.newObject();
        properties.put("name", name);
        Promise<Rule> rule = Rule.nodes.full(properties);
        Promise<Tuple<List<Part>, Rule>> results = globalPartsList.zip(rule);
        return results.map(new Function<Tuple<List<Part>, Rule>, Result>() {
            public Result apply(Tuple<List<Part>, Rule> results) {
                return ok(output.render(results._1, results._2));
            }
        });
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> lhs(String name) {
        ObjectNode properties = Json.newObject();
        properties.put("name", name);
        Promise<Rule> rule = Rule.nodes.get(properties);
        Promise<JsonNode> lhsJSON = rule.flatMap(new Function<Rule, Promise<JsonNode>>() {
            public Promise<JsonNode> apply(Rule rule) {
                ObjectNode properties = Json.newObject();
                String uuid = UUIDGenerator.from(rule.uuid);
                properties.put("uuid", uuid);
                properties.put("ruleUUID", rule.uuid);
                Promise<LHS> lhs = LHS.nodes.get(properties);
                return lhs.map(new Function<LHS, JsonNode>() {
                    public JsonNode apply(LHS lhs) {
                        return lhs.json;
                    }
                });
            }
        });
        return lhsJSON.map(new Function<JsonNode, Result>() {
            public Result apply(JsonNode lhsJSON) {
                ObjectNode result = Json.newObject();
                result.put("json", lhsJSON);
                return ok(result);
            }
        });
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> rhs(String name) {
        ObjectNode properties = Json.newObject();
        properties.put("name", name);
        Promise<Rule> rule = Rule.nodes.get(properties);
        Promise<JsonNode> rhsJSON = rule.flatMap(new Function<Rule, Promise<JsonNode>>() {
            public Promise<JsonNode> apply(Rule rule) {
                ObjectNode properties = Json.newObject();
                String uuid = UUIDGenerator.from(rule.uuid);
                properties.put("uuid", uuid);
                Promise<RHS> rhs = RHS.nodes.get(properties);
                return rhs.map(new Function<RHS, JsonNode>() {
                    public JsonNode apply(RHS rhs) {
                        return rhs.json;
                    }
                });
            }
        });
        return rhsJSON.map(new Function<JsonNode, Result>() {
            public Result apply(JsonNode rhsJSON) {
                ObjectNode result = Json.newObject();
                result.put("json", rhsJSON);
                return ok(result);
            }
        });
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> create() {
        final JsonNode json = request().body().asJson();
        Promise<Boolean> created = Rule.nodes.create(json);
        return created.map(new Function<Boolean, Result>() {
            ObjectNode result = Json.newObject();

            public Result apply(Boolean created) {
                if (created) {
                    String name = json.get("name").asText();
                    result.put("id", name);
                    result.put("name", name);
                    result.put("description", json.get("description").asText());
                    return ok(result);
                }
                return badRequest(result);
            }
        });
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> updateName(final String name) {
        final ObjectNode newProps = (ObjectNode) request().body().asJson();
        newProps.retain("uuid", "name", "description");
        Promise<Boolean> nameTaken = Rule.nodes.exists(newProps);
        Promise<Boolean> updated = nameTaken.flatMap(new Function<Boolean, Promise<Boolean>>() {
            public Promise<Boolean> apply(Boolean nameTaken) {
                if (nameTaken) {
                    return Promise.pure(false);
                }
                ObjectNode oldProps = Json.newObject();
                oldProps.put("name", name);
                return Rule.nodes.update(oldProps, newProps);
            }
        });
        return updated.map(new Function<Boolean, Result>() {
            ObjectNode result = Json.newObject();

            public Result apply(Boolean updated) {
                if (updated) {
                    result.put("id", newProps.get("name").asText());
                    result.put("message", "Name successfully updated.");
                    return ok(result);
                }
                result.put("message", "Name not updated.");
                return badRequest(result);
            }
        });
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> updateDescription(String name) {
        ObjectNode newProps = (ObjectNode) request().body().asJson();
        newProps.retain("uuid", "name", "description");
        ObjectNode oldProps = newProps.deepCopy().retain("name");
        Promise<Boolean> updated = Rule.nodes.update(oldProps, newProps);
        return updated.map(new Function<Boolean, Result>() {
            ObjectNode result = Json.newObject();

            public Result apply(Boolean updated) {
                if (updated) {
                    result.put("message", "Description successfully updated.");
                    return ok(result);
                }
                result.put("message", "Description not updated.");
                return badRequest(result);
            }
        });
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> addFeature(String name) {
        JsonNode json = request().body().asJson();
        final ObjectNode avm = (ObjectNode) json.deepCopy();
        avm.retain("ruleUUID", "uuid");
        final ObjectNode feature = Json.newObject();
        feature.put("name", json.findValue("name").asText());
        feature.put("type", json.findValue("type").asText());
        Promise<Boolean> added = Substructure.nodes.connect(avm, feature);
        Promise<Feature> feat = Feature.nodes.get(feature);
        return added.zip(feat).map(new Function<Tuple<Boolean, Feature>, Result>() {
            ObjectNode result = Json.newObject();

            public Result apply(Tuple<Boolean, Feature> t) {
                Boolean added = t._1;
                if (added) {
                    Feature feat = t._2;
                    if (feat.isComplex()) {
                        String parentUUID = avm.get("uuid").asText();
                        String featureUUID = feat.getUUID();
                        String uuid = UUIDGenerator.from(parentUUID + featureUUID);
                        ObjectNode value = Json.newObject();
                        value.put("uuid", uuid);
                        value.putArray("pairs");
                        result.put("value", value);
                    } else {
                        result.put("value", new TextNode("underspecified"));
                    }
                    result.put("message", "Feature successfully added.");
                    return ok(result);
                }
                result.put("message", "Feature not added.");
                return badRequest(result);
            }
        });
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> updateFeatureValue(String name) {
        JsonNode json = request().body().asJson();
        ObjectNode avm = (ObjectNode) json.deepCopy();
        avm.retain("ruleUUID", "uuid");
        ObjectNode feature = Json.newObject();
        feature.put("name", json.findValue("name").asText());
        ObjectNode value = Json.newObject();
        value.put("name", json.findValue("value").asText());
        ObjectNode newValue = Json.newObject();
        newValue.put("name", json.findValue("newValue"));
        Promise<Boolean> updated = Substructure.nodes.setValue(avm, feature, value, newValue);
        return updated.map(new Function<Boolean, Result>() {
            ObjectNode result = Json.newObject();

            public Result apply(Boolean updated) {
                if (updated) {
                    result.put("message", "Feature successfully updated.");
                    return ok(result);
                }
                result.put("message", "Feature not updated.");
                return badRequest(result);
            }
        });
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> removeFeature(String name) {
        JsonNode json = request().body().asJson();
        ObjectNode avm = (ObjectNode) json.deepCopy();
        avm.retain("ruleUUID", "uuid");
        ObjectNode feature = Json.newObject();
        feature.put("name", json.findValue("name").asText());
        feature.put("type", json.findValue("type").asText());
        Promise<Boolean> removed = Substructure.nodes.disconnect(avm, feature);
        return removed.map(new Function<Boolean, Result>() {
            ObjectNode result = Json.newObject();

            public Result apply(Boolean removed) {
                if (removed) {
                    result.put("message", "Feature successfully removed.");
                    return ok(result);
                }
                result.put("message", "Feature not removed.");
                return badRequest(result);
            }
        });
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> addString(String name, String groupID) {
        JsonNode json = request().body().asJson();
        ObjectNode group = Json.newObject();
        group.put("uuid", groupID);
        ObjectNode string = Json.newObject();
        String uuid = UUIDGenerator.from(json.get("content").asText());
        string.put("uuid", uuid);
        string.put("content", json.get("content").asText());
        Promise<Boolean> connected = CombinationGroup.nodes.connect(group, string);
        ObjectNode result = Json.newObject();
        result.put("id", uuid);
        return connected.map(new ResultFunction("String successfully added.", "String not added.", result));

    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> updateString(String name, String groupID, String stringID) {
        JsonNode json = request().body().asJson();
        final ObjectNode group = Json.newObject();
        group.put("uuid", groupID);
        final ObjectNode oldString = Json.newObject();
        oldString.put("uuid", stringID);
        ObjectNode newString = Json.newObject();
        String content = json.findValue("content").asText();
        String uuid = UUIDGenerator.from(content);
        newString.put("content", content);
        newString.put("uuid", uuid);
        final ObjectNode result = Json.newObject();
        result.put("id", uuid);
        Promise<Boolean> updated = CombinationGroup.nodes.update(group, oldString, newString);
        return updated.map(new ResultFunction("String successfully updated.", "String not updated.", result));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> removeString(String name, String groupID, String stringID) {
        ObjectNode group = Json.newObject();
        group.put("uuid", groupID);
        final ObjectNode string = Json.newObject();
        string.put("uuid", stringID);
        string.put("nodeType", "string");
        Promise<Boolean> removed = CombinationGroup.nodes.disconnect(group, string);
        return removed.map(new ResultFunction("String successfully removed.", "String not removed."));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> addGroup(String name) {
        final JsonNode json = request().body().asJson();
        ObjectNode rhs = Json.newObject();
        rhs.put("uuid", json.findValue("rhsID").asText());
        final ObjectNode group = Json.newObject();
        final String uuid = UUIDGenerator.random();
        group.put("uuid", uuid);
        group.put("position", json.findValue("position").asInt());
        final ObjectNode result = Json.newObject();
        result.put("id", uuid);
        Promise<Boolean> added = RHS.nodes.connect(rhs, group);
        return added.map(new ResultFunction("Group successfully added.", "Group not added.", result));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> updateGroup(String name, String groupID) {
        JsonNode json = request().body().asJson();
        ObjectNode oldProps = Json.newObject();
        oldProps.put("uuid", groupID);
        ObjectNode newProps = oldProps.deepCopy();
        newProps.put("position", json.findValue("position").asInt());
        Promise<Boolean> updated = CombinationGroup.nodes.update(oldProps, newProps);
        return updated.map(new ResultFunction("Group successfully updated.", "Group not updated."));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> removeGroup(String name, final String groupID) {
        ObjectNode properties = Json.newObject();
        properties.put("name", name);
        Promise<Rule> rule = Rule.nodes.get(properties);
        Promise<Boolean> removed = rule.flatMap(new Function<Rule, Promise<Boolean>>() {
            public Promise<Boolean> apply(Rule rule) {
                String uuid = UUIDGenerator.from(rule.uuid);
                ObjectNode rhs = Json.newObject();
                rhs.put("uuid", uuid);
                ObjectNode group = Json.newObject();
                group.put("uuid", groupID);
                return RHS.nodes.disconnect(rhs, group);
            }
        });
        return removed.map(new ResultFunction("Group successfully removed.", "Group not removed."));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> addSlot(String name, final String groupID) {
        JsonNode json = request().body().asJson();
        ObjectNode group = Json.newObject();
        group.put("uuid", groupID);
        final ObjectNode slot = Json.newObject();
        final String uuid = UUIDGenerator.random();
        slot.put("uuid", uuid);
        slot.put("position", json.findValue("position").asInt());
        final ObjectNode result = Json.newObject();
        result.put("id", uuid);
        Promise<Boolean> added = CombinationGroup.nodes.connect(group, slot);
        return added.map(new ResultFunction("Slot successfully added.", "Slot not added", result));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> updateSlot(String name, String groupID, String slotID) {
        JsonNode json = request().body().asJson();
        ObjectNode oldProps = Json.newObject();
        oldProps.put("uuid", slotID);
        ObjectNode newProps = oldProps.deepCopy();
        newProps.put("position", json.findValue("position").asInt());
        Promise<Boolean> updated = Slot.nodes.update(oldProps, newProps);
        return updated.map(new ResultFunction("Slot successfully updated.", "Slot not updated."));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> removeSlot(String name, String groupID, String slotID) {
        ObjectNode group = Json.newObject();
        group.put("uuid", groupID);
        ObjectNode slot = Json.newObject();
        slot.put("uuid", slotID);
        slot.put("nodeType", "slot");
        Promise<Boolean> removed = CombinationGroup.nodes.disconnect(group, slot);
        return removed.map(new ResultFunction("Slot successfully removed.", "Slot not removed."));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> addPart(String name, String groupID, String slotID) {
        JsonNode json = request().body().asJson();
        ObjectNode slot = Json.newObject();
        slot.put("uuid", slotID);
        ObjectNode part = Json.newObject();
        String content = json.findValue("content").asText();
        String uuid = UUIDGenerator.from(content);
        part.put("uuid", uuid);
        part.put("content", content);
        Promise<Boolean> connected = Slot.nodes.connect(slot, part);
        ObjectNode result = Json.newObject();
        result.put("id", uuid);
        return connected.map(new ResultFunction("Part successfully added.", "Part not added.", result));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> updatePart(String name, String groupID, String slotID, String partID) {
        JsonNode json = request().body().asJson();
        final ObjectNode slot = Json.newObject();
        slot.put("uuid", slotID);
        final ObjectNode oldPart = Json.newObject();
        oldPart.put("uuid", partID);
        ObjectNode newPart = Json.newObject();
        String content = json.findValue("content").asText();
        String uuid = UUIDGenerator.from(content);
        newPart.put("content", content);
        newPart.put("uuid", uuid);
        final ObjectNode result = Json.newObject();
        result.put("id", uuid);
        Promise<Boolean> updated = Slot.nodes.update(slot, oldPart, newPart);
        return updated.map(new ResultFunction("Part successfully updated.", "Part not updated.", result));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> removePart(String name, String groupID, String slotID, String partID) {
        ObjectNode slot = Json.newObject();
        slot.put("uuid", slotID);
        final ObjectNode part = Json.newObject();
        part.put("uuid", partID);
        Promise<Boolean> removed = Slot.nodes.disconnect(slot, part);
        return removed.map(new ResultFunction("Part successfully removed.", "Part not removed."));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> addRef(String name, String groupID, String slotID) {
        JsonNode json = request().body().asJson();
        String ruleName = json.findValue("ruleName").asText();
        Promise<Boolean> added;
        if (name.equals(ruleName)) {
            added = Promise.pure(false);
            return added.map(
                    new ResultFunction("Cross-reference successfully added.", "Can't add circular dependency."));
        } else {
            ObjectNode result = Json.newObject();
            result.put("id", ruleName);
            ObjectNode slot = Json.newObject();
            slot.put("uuid", slotID);
            ObjectNode rule = Json.newObject();
            rule.put("name", ruleName);
            added = Slot.nodes.connect(slot, rule);
            return added.map(new ResultFunction("Cross-reference successfully added.", "Cross-reference not added.",
                    result));
        }
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> removeRef(String name, String groupID, String slotID, String refID) {
        ObjectNode slot = Json.newObject();
        slot.put("uuid", slotID);
        ObjectNode rule = Json.newObject();
        rule.put("name", refID);
        Promise<Boolean> removed = Slot.nodes.disconnect(slot, rule);
        return removed.map(new ResultFunction("Part successfully removed.", "Part not removed."));
    }

    @Security.Authenticated(Secured.class)
    @BodyParser.Of(BodyParser.Json.class)
    public static Promise<Result> delete(final String name) {
        final ObjectNode rule = Json.newObject();
        rule.put("name", name);
        // 1. Check if rule is orphaned
        Promise<Boolean> orphaned = Rule.nodes.orphaned(rule);
        // 2. If it is, delete it
        Promise<Boolean> deleted = orphaned.flatMap(new Function<Boolean, Promise<Boolean>>() {
            public Promise<Boolean> apply(Boolean orphaned) {
                if (orphaned) {
                    Promise<Rule> r = Rule.nodes.get(rule);
                    Promise<Boolean> deleted = r.flatMap(new Function<Rule, Promise<Boolean>>() {
                        public Promise<Boolean> apply(Rule r) {
                            rule.put("uuid", r.uuid);
                            return Rule.nodes.delete(rule);
                        }
                    });
                    return deleted;
                }
                return Promise.pure(false);
            }
        });
        return deleted.map(new Function<Boolean, Result>() {
            ObjectNode result = Json.newObject();

            public Result apply(Boolean deleted) {
                if (deleted) {
                    return ok(result);
                }
                return badRequest(result);
            }
        });
    }

    private static class ResultFunction implements Function<Boolean, Result> {
        private String successMsg;
        private String errorMsg;
        private ObjectNode result;

        public ResultFunction(String successMsg, String errorMsg) {
            this.successMsg = successMsg;
            this.errorMsg = errorMsg;
        }

        public ResultFunction(String successMsg, String errorMsg, ObjectNode result) {
            this(successMsg, errorMsg);
            this.result = result;
        }

        public Result apply(Boolean actionSuccessful) {
            ObjectNode result = (this.result == null) ? Json.newObject() : this.result;
            if (actionSuccessful) {
                result.put("message", successMsg);
                return ok(result);
            }
            result.put("message", errorMsg);
            return badRequest(result);
        }
    }

}