All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.neo4j.driver.internal.summary.InternalPlan Maven / Gradle / Ivy

/*
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [http://neo4j.com]
 *
 * This file is part of Neo4j.
 *
 * 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.neo4j.driver.internal.summary;

import static java.lang.String.format;
import static org.neo4j.driver.Values.ofString;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.neo4j.driver.Value;
import org.neo4j.driver.Values;
import org.neo4j.driver.summary.Plan;

public class InternalPlan implements Plan {
    private final String operatorType;
    private final List identifiers;
    private final Map arguments;
    private final List children;

    // Only call when sub-classing, for constructing plans, use .plan instead
    protected InternalPlan(
            String operatorType, Map arguments, List identifiers, List children) {
        this.operatorType = operatorType;
        this.identifiers = identifiers;
        this.arguments = arguments;
        this.children = children;
    }

    @Override
    public String operatorType() {
        return operatorType;
    }

    @Override
    public List identifiers() {
        return identifiers;
    }

    @Override
    public Map arguments() {
        return arguments;
    }

    @Override
    public List children() {
        return children;
    }

    @Override
    public String toString() {
        return format(
                "SimplePlanTreeNode{operatorType='%s', arguments=%s, identifiers=%s, children=%s}",
                operatorType, arguments, identifiers, children);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        InternalPlan that = (InternalPlan) o;

        return operatorType.equals(that.operatorType)
                && arguments.equals(that.arguments)
                && identifiers.equals(that.identifiers)
                && children.equals(that.children);
    }

    @Override
    public int hashCode() {
        int result = operatorType.hashCode();
        result = 31 * result + identifiers.hashCode();
        result = 31 * result + arguments.hashCode();
        result = 31 * result + children.hashCode();
        return result;
    }

    public static Plan plan(
            String operatorType, Map arguments, List identifiers, List children) {
        return EXPLAIN_PLAN.create(operatorType, arguments, identifiers, children, null);
    }

    public static final PlanCreator EXPLAIN_PLAN = new PlanCreator() {
        @Override
        public Plan create(
                String operatorType,
                Map arguments,
                List identifiers,
                List children,
                Value originalPlanValue) {
            return new InternalPlan<>(operatorType, arguments, identifiers, children);
        }
    };

    /** Builds a regular plan without profiling information - eg. a plan that came as a result of an `EXPLAIN` query */
    public static final Function EXPLAIN_PLAN_FROM_VALUE = new Converter<>(EXPLAIN_PLAN);

    /**
     * Since a plan with or without profiling looks almost the same, we just keep two impls. of this
     * around to contain the small difference, and share the rest of the code for building plan trees.
     * @param 
     */
    interface PlanCreator {
        T create(
                String operatorType,
                Map arguments,
                List identifiers,
                List children,
                Value originalPlanValue);
    }

    static class Converter implements Function {
        private final PlanCreator planCreator;

        public Converter(PlanCreator planCreator) {
            this.planCreator = planCreator;
        }

        @Override
        public T apply(Value plan) {
            final String operatorType = plan.get("operatorType").asString();

            final Value argumentsValue = plan.get("args");
            final Map arguments = argumentsValue.isNull()
                    ? Collections.emptyMap()
                    : argumentsValue.asMap(Values.ofValue());

            final Value identifiersValue = plan.get("identifiers");
            final List identifiers =
                    identifiersValue.isNull() ? Collections.emptyList() : identifiersValue.asList(ofString());

            final Value childrenValue = plan.get("children");
            final List children = childrenValue.isNull() ? Collections.emptyList() : childrenValue.asList(this);

            return planCreator.create(operatorType, arguments, identifiers, children, plan);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy