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

org.objectfabric.FileGeneratorMethod Maven / Gradle / Ivy

There is a newer version: 0.9.1
Show newest version
/**
 * This file is part of ObjectFabric (http://objectfabric.org).
 *
 * ObjectFabric is licensed under the Apache License, Version 2.0, the terms
 * of which may be found at http://www.apache.org/licenses/LICENSE-2.0.html.
 * 
 * Copyright ObjectFabric Inc.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

package org.objectfabric;

// TODO: send only arguments delta between two calls to same method
class FileGeneratorMethod {

    private final GeneratorBase _gen;

    private final FileGeneratorClass _writer;

    private final MethodDef _method;

    FileGeneratorMethod(FileGeneratorClass writer, MethodDef method) {
        _gen = writer.g();
        _writer = writer;
        _method = method;
    }

    void writeCalls() {
        String args = "";
        String argsNames = "";

        for (int i = 0; i < _method.Arguments.size(); i++) {
            String name = _method.Arguments.get(i).Name;
            String arg = _method.Arguments.get(i).type().fullName(_gen.target(), true) + " " + name;

            if (args.length() == 0) {
                args += arg;
                argsNames += name;
            } else {
                args += ", " + arg;
                argsNames += ", " + name;
            }
        }

        String final_ = _gen.isJava() ? "final " : "";
        String generic = "";

        if (_method.ReturnValue.type().otherClass() == Platform.get().voidClass())
            generic += _gen.isJava() ? "" : "";
        else
            generic += "<" + _method.ReturnValue.type().fullNameWithGenericsAndBoxPrimitives(_gen.target()) + ">";

        String name = _method.nameWithRightCaps(_gen);
        String comma = args.length() > 0 ? ", " : "";
        String visibility = _method.Public ? "public" : "protected";
        String returnType = _method.ReturnValue.type().fullName(_gen.target(), true);
        String returnVarType = returnType;
        String returnStatement = "return ";
        String executor = _gen.isJava() ? "java.util.concurrent.Executor" : "System.Threading.Tasks.TaskScheduler";
        String future = _gen.isJava() ? "java.util.concurrent.Future" : "System.Threading.Tasks.Task";
        boolean returnVoid = false;

        if (_method.ReturnValue.type().otherClass() == Platform.get().voidClass()) {
            returnVarType = "java.lang.Void";
            returnStatement = "";
            returnVoid = true;
        }

        wl();

        writeComments("");

        wl("    " + visibility + " " + final_ + returnType + " " + name + "(" + args + ") {");
        wl("        " + returnStatement + name + "(" + argsNames + comma + "getMethodExecutor());");
        wl("    }");
        wl();

        writeComments("Specifies the Executor or TaskScheduler that will run the method. For replicated objects, the method runs by default on the site the object has been created, using site's method executor.");

        wl("    " + visibility + " " + final_ + returnType + " " + name + "(" + args + comma + executor + " executor) {");
        wl("        if (executor == getTransparentExecutor_())");
        wl("            " + returnStatement + name + "Implementation(" + argsNames + ");");
        wl("        else {");
        wl("            " + future + generic + " future_ = " + name + "Async(" + argsNames + comma + (_gen.isJava() ? "getNopCallback_(), null, " : "") + "executor);");

        if (_gen.isJava()) {
            wl();
            wl("            try {");
            wl("                " + returnStatement + "future_.get();");
            wl("            } catch (java.lang.InterruptedException ex_) {");
            wl("                throw new java.lang.RuntimeException(ex_);");
            wl("            } catch (java.util.concurrent.ExecutionException ex_) {");
            wl("                if (ex_.getCause() instanceof java.lang.RuntimeException)");
            wl("                    throw (java.lang.RuntimeException) ex_.getCause();");
            wl();
            wl("                throw new java.lang.RuntimeException(ex_.getCause());");
            wl("            }");
        } else {
            wl("            " + returnStatement + "future_.Result;");
        }

        wl("        }");
        wl("    }");
        wl();

        writeComments("Asynchronous version.");

        String callback = _gen.isJava() ? comma + "org.objectfabric.AsyncCallback" + generic + " callback" : "";

        wl("    " + visibility + " " + final_ + future + generic + " " + name + "Async(" + args + callback + ") {");
        wl("        return " + name + "Async(" + argsNames + comma + (_gen.isJava() ? "callback, " : "") + "getMethodExecutor());");
        wl("    }");
        wl();

        writeComments("Asynchronous version, and specifies the Executor or TaskScheduler that will run the method. For replicated objects,",
                "the method runs by default on the site the object has been created. @see Site.getMethodExecutor() to specify an execution site.");

        String asyncArgs;

        if (_gen.isJava())
            asyncArgs = args + comma + "org.objectfabric.AsyncCallback" + generic + " callback, ";
        else
            asyncArgs = args + comma;

        wl("    " + visibility + " " + final_ + future + generic + " " + name + "Async(" + asyncArgs + executor + " executor) {");
        wl("        if (executor == getTransparentExecutor_()) {");
        wl("            " + returnVarType + " result_ = " + _method.ReturnValue.type().defaultString() + ";");
        wl("            java.lang.Exception exception_ = null;");
        wl();
        wl("            try {");
        wl("                " + (returnVoid ? "" : "result_ = ") + name + "Implementation(" + argsNames + ");");
        wl("            } catch (java.lang.Exception e_) {");
        wl("                exception_ = e_;");
        wl("            }");
        wl();
        wl("            return getCompletedFuture_(result_, exception_" + (_gen.isJava() ? ", callback" : "") + ");");
        wl("        } else {");

        String type = _method.fullType(_gen);
        wl("            " + type + " instance_ = " + type + ".getOrCreateInstance(getFabric());");
        wl("            " + type + ".Version version_ = (" + type + ".Version) getSharedVersion_(instance_);");
        wl("            version_.clearBits();");

        for (int i = 0; i < _method.Arguments.size(); i++) {
            ArgumentDef arg = _method.Arguments.get(i);

            wl("            version_._" + arg.Name + " = " + arg.Name + ";");
            wl("            version_.setBit(" + _method.fullType(_gen) + "." + arg.nameAsConstant() + "_INDEX);");
        }

        if (_gen.isJava()) {
            String methodArgs = "this, instance_, METHOD_" + _method.indexInClass() + ", callback";
            wl("            org.objectfabric.TObject.UserTObject.LocalMethodCall call_ = new org.objectfabric.TObject.UserTObject.LocalMethodCall(" + methodArgs + ");");
        } else
            wl("            LocalMethodCall" + generic + " call_ = new LocalMethodCall" + generic + "(this, instance_, METHOD_" + _method.indexInClass() + ", callback, asyncOptions);");

        if (_gen.isJava())
            wl("            executor.execute(call_);");
        else
            wl("            call_.Task.Start( executor );");

        wl("            return call_" + (_gen.isCSharp() ? ".Task" : "") + ";");
        wl("        }");
        wl("    }");

        if (_gen.isJava()) {
            wl();
            wl("    /**");
            wl("     * Override to implement the method.");
            wl("     */");
            wl("    protected " + _method.ReturnValue.type().fullName(_gen.target(), true) + " " + name + "Implementation(" + args + ") {");
            wl("        throw new java.lang.RuntimeException(org.objectfabric.Strings.MISSING_METHOD_CALL_IMPLEMENTATION);");
            wl("    }");
            wl();
            wl("    /**");
            wl("     * Override to implement the method asynchronously.");
            wl("     */");
            wl("    protected void " + name + "ImplementationAsync(" + args + comma + "org.objectfabric.MethodCall call) {");
            wl("        try {");

            if (returnVoid) {
                wl("            " + name + "Implementation(" + argsNames + ");");
                wl("            call.set(null);");
            } else
                wl("            call.set(" + name + "Implementation(" + argsNames + "));");

            wl("        } catch (java.lang.Exception e_) {");
            wl("            call.setException(e_);");
            wl("        }");
            wl("    }");
        }
    }

    private void writeComments(String... lines) {
        wl("    /**");

        if (_method.Comment != null && _method.Comment.length() > 0) {
            wl("     * " + _method.Comment);
            wl("     * ");
        }

        for (String line : lines)
            wl("     * " + line);

        wl("     */");
    }

    void writeInvocation() {
        String args = "";

        if (_method.Arguments.size() > 0) {
            wl("                " + _method.fullType(_gen) + ".Version version_ = (" + _method.fullType(_gen) + ".Version) getMethodVersion_(call);");

            for (int i = 0; i < _method.Arguments.size(); i++) {
                String type = _method.Arguments.get(i).type().fullName(_gen.target(), true);
                String name = _method.Arguments.get(i).Name;
                String default_ = _method.Arguments.get(i).type().defaultString();
                wl("                " + type + " " + name + " = version_ != null ? (" + type + ") version_._" + name + " : " + default_ + ";");
                args += name + ", ";
            }

            wl();
        }

        wl("                try {");
        wl("                    " + _method.nameWithRightCaps(_gen) + "ImplementationAsync(" + args + "call);");
        wl("                } catch (java.lang.Exception e_) {");
        wl("                    call.setException(e_);");
        wl("                }");
        wl();
    }

    void writeResult() {
        wl("                " + _method.fullType(_gen) + ".Version version = (" + _method.fullType(_gen) + ".Version) getMethodVersion_(call);");
        wl();
        wl("                if (version.__error == null)");

        if (_method.ReturnValue.type().otherClass() != Platform.get().voidClass())
            wl("                    call.set(version.__return);");
        else
            wl("                    call.set(null);");

        wl("                else");
        wl("                    call.setException(new org.objectfabric.ReplicatedException(version.__error));");
    }

    private void wl(String line) {
        _writer.wl(line);
    }

    private void wl() {
        _writer.wl();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy