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

org.objectfabric.FileGeneratorValueSet 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;

class FileGeneratorValueSet {

    private final GeneratorBase _gen;

    private final ValueSetDef _valueSet;

    private final FileGenerator _file;

    FileGeneratorValueSet(GeneratorBase generator, ValueSetDef valueSet, FileGenerator file) {
        _gen = generator;
        _valueSet = valueSet;
        _file = file;
    }

    private String getVersionName() {
        if (_valueSet.lessOr32Fields(_gen.objectModel()))
            return "Version32";

        return "VersionN";
    }

    private void writeFieldGet(ValueDef value) {
        Immutable immutable = value.type().immutable();
        immutable = immutable != null ? immutable : value.type().customUnderlyingImmutable();
        String default_ = immutable != null ? immutable.defaultString() : "null";

        wl("        org.objectfabric.TObject.Transaction outer = current_();");
        wl("        org.objectfabric.TObject.Transaction inner = startRead_(outer);");
        wl("        Version v = (Version) get" + getVersionName() + "_(inner, " + value.nameAsConstant() + "_INDEX);");
        wl("        " + value.type().fullName(_gen.target(), true) + " value = v != null ? v._" + value.Name + " : " + default_ + ";");
        wl("        endRead_(outer, inner);");
        wl("        return value;");
    }

    private void writeFieldGetReadOnly(ValueDef value) {
        wl("        Version v = (Version) shared_();");
        wl("        return v._" + value.Name + ";");
    }

    private void writeFieldSet(ValueDef value) {
        if (value.type().isTObject()) {
            wl("        if (value.resource() != resource())");
            wl("            wrongResource_();");
            wl();
        } else if (value.type().canBeTObject()) {
            wl("        if (value instanceof org.objectfabric.TObject && ((org.objectfabric.TObject) value).resource() != resource())");
            wl("            wrongResource_();");
            wl();
        }

        wl("        org.objectfabric.TObject.Transaction outer = current_();");
        wl("        org.objectfabric.TObject.Transaction inner = startWrite_(outer);");
        wl("        Version v = (Version) getOrCreateVersion_(inner);");

        if (value.type().canBeTObject())
            wl("        v._" + value.Name + " = value;");
        else
            wl("        v._" + value.Name + " = value;");

        wl("        v.setBit(" + value.nameAsConstant() + "_INDEX);");
        wl("        endWrite_(outer, inner);");
    }

    private void writeField(int index) {
        if (Debug.ENABLED)
            Debug.assertion(!(_valueSet instanceof MethodDef));

        wl();

        ValueDef value = _valueSet.value(index);
        String readVisibility = (value.publicVisibility().equals(FieldDef.TRUE) || value.publicVisibility().equals(FieldDef.READ)) ? "public" : "protected";
        String writeVisibility = value.publicVisibility().equals(FieldDef.TRUE) ? "public" : "protected";
        String type = value.type().fullName(_gen.target(), true);

        if (_gen.isCSharp()) {
            if (value.Comment != null && value.Comment.length() > 0) {
                wl("    /// ");
                wl("    /// " + value.Comment);
                wl("    /// ");
            }

            wl("    public " + type + " " + Utils.getWithFirstLetterUp(value.Name));
            wl("    {");
            wl("        get");
            wl("        {");
            tab();

            if (value.isReadOnly())
                writeFieldGetReadOnly(value);
            else
                writeFieldGet(value);

            untab();
            wl("        }");

            if (!value.isReadOnly()) {
                wl("        set");
                wl("        {");

                tab();
                writeFieldSet(value);
                untab();

                wl("        }");
            }

            wl("    }");
        } else {
            // Getter
            {
                if (value.Comment != null && value.Comment.length() > 0)
                    wl("    /** " + value.Comment + " */");

                wl("    " + readVisibility + " final " + type + " " + value.Name + "() {");

                if (value.isReadOnly())
                    writeFieldGetReadOnly(value);
                else
                    writeFieldGet(value);
                wl("    }");
            }

            // TODO: generate async getter if field is transient
            // + if (_gen.getFlags().contains(Flag.GenerateSynchronousMethods))

            if (!value.isReadOnly()) { // Setter
                wl();

                if (value.Comment != null && value.Comment.length() > 0)
                    wl("    /** " + value.Comment + " */");

                wl("    " + writeVisibility + " final void " + value.Name + "(" + type + " value) {");

                writeFieldSet(value);

                wl("    }");
            }
        }
    }

    final void writeType() {
        wl();

        ObjectModelDef model = _gen.objectModel();
        String m = model.rootPackage().Name + "." + model.Name + (_gen.isCSharp() ? ".Instance" : ".instance()");
        String c = model.fullName() + "." + getClassId();

        if (_gen.isCSharp()) {
            wl("    #pragma warning disable 109");
            wl("    new public static readonly org.objectfabric.TType TYPE = getTType_(" + m + ", " + c + ");");
            wl("    #pragma warning restore 109");
        } else
            wl("    public static final org.objectfabric.TType TYPE = new org.objectfabric.TType(" + m + ", " + c + ");");
    }

    final void writeFields() {
        for (int i = 0; i < _valueSet.values().size(); i++)
            writeField(i);
    }

    final void writeFieldsConstantsAndCount() {
        int startIndex = 0;

        ClassDef parent = _valueSet.parentGeneratedClass(_gen.objectModel());

        if (parent != null)
            startIndex = parent.allValues(_gen.objectModel()).size();

        for (int i = 0; i < _valueSet.values().size(); i++) {
            wl();

            String constant = _valueSet.value(i).nameAsConstant();
            String visibility = _valueSet.value(i).publicVisibility().equals(FieldDef.TRUE) ? "public" : "protected";

            wl("    " + visibility + " static final int " + constant + "_INDEX = " + startIndex++ + ";");
            wl();

            String name = "\"" + _valueSet.value(i).Name + "\"";

            wl("    " + visibility + " static final " + _gen.target().stringString() + " " + constant + "_NAME = " + name + ";");
            wl();

            String t = _valueSet.value(i).type().getTTypeString(_gen.target());
            wl("    " + visibility + " static " + (_gen.isCSharp() ? "readonly" : "final") + " org.objectfabric.TType " + constant + "_TYPE = " + t + ";");
        }

        wl();
        wl("    public static final int FIELD_COUNT = " + _valueSet.allValues(_gen.objectModel()).size() + ";");
        wl();

        String s = _gen.isCSharp() ? "GetField" : "field";

        wl("    public static " + _gen.target().stringString() + " " + s + "Name(int index) {");
        wl("        switch (index) {");

        for (int i = 0; i < _valueSet.values().size(); i++) {
            String constant = _valueSet.value(i).nameAsConstant();

            wl("            case " + constant + "_INDEX:");
            wl("                return " + constant + "_NAME;");
        }

        wl("            default:");

        if (_valueSet.parent() != null)
            wl("                return " + _valueSet.parent().fullName(_gen.target()) + "." + s + "Name(index);");
        else
            wl("                throw new IllegalArgumentException();");

        wl("        }");
        wl("    }");
        wl();
        wl("    public static org.objectfabric.TType " + s + "Type(int index) {");
        wl("        switch (index) {");

        for (int i = 0; i < _valueSet.values().size(); i++) {
            String constant = _valueSet.value(i).nameAsConstant();

            wl("            case " + _valueSet.value(i).nameAsConstant() + "_INDEX:");
            wl("                return " + constant + "_TYPE;");
        }

        wl("            default:");

        if (_valueSet.parent() != null)
            wl("                return " + _valueSet.parent().fullName(_gen.target()) + "." + s + "Type(index);");
        else
            wl("                throw new IllegalArgumentException();");

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

    final void writeVersion() {
        String visibility = _valueSet instanceof MethodDef ? "public " : "protected ";
        String static_ = _gen.isCSharp() ? "" : "static ";
        String new_ = _gen.isCSharp() ? "new " : "";

        wl();

        String parent;

        if (_valueSet.parent() != null)
            parent = _valueSet.parent().fullName(_gen.target()) + ".Version";
        else {
            if (_valueSet.lessOr32Fields(_gen.objectModel()))
                parent = "org.objectfabric.TIndexed.Version32";
            else
                parent = "org.objectfabric.TIndexed.VersionN";
        }

        wl("    " + new_ + visibility + static_ + "class Version " + _gen.target().extendsString() + " " + parent + " {");

        for (int i = 0; i < _valueSet.values().size(); i++) {
            ValueDef value = _valueSet.value(i);
            wl();
            wl("        public " + value.type().fullName(_gen.target()) + " _" + value.Name + ";");
        }

        for (TypeDef type : _valueSet.enums()) {
            wl();
            String c = type.fullName(_gen.target());
            String name = ObjectModelDef.formatAsConstant(c) + TypeDef.ENUM_VALUES_ARRAY;
            wl("        private static final " + c + "[] " + name + " = " + c + ".values();");
        }

        boolean hasReadOnlys = false;

        if (!(_valueSet instanceof MethodDef)) {
            List all = _valueSet.allValues(_gen.objectModel());

            for (int i = 0; i < all.size(); i++)
                if (all.get(i).isReadOnly())
                    hasReadOnlys = true;

            String final_ = _gen.isCSharp() ? "readonly" : "final";

            if (hasReadOnlys) {
                wl();

                if (_valueSet.lessOr32Fields(_gen.objectModel()))
                    wl("        private static " + final_ + " int _readOnlys;");
                else
                    wl("        private static " + final_ + " org.objectfabric.misc.Bits.Entry[] _readOnlys;");
            }

            wl();
            wl("        static" + (_gen.isCSharp() ? " Version()" : "") + " {");

            if (hasReadOnlys) {
                if (_valueSet.lessOr32Fields(_gen.objectModel()))
                    wl("            int readOnlys = 0;");
                else
                    wl("            org.objectfabric.misc.Bits.Entry[] readOnlys = new org.objectfabric.misc.Bits.Entry[org.objectfabric.misc.Bits.SPARSE_BITSET_DEFAULT_CAPACITY];");

                for (int i = 0; i < all.size(); i++)
                    if (all.get(i).isReadOnly())
                        wl("            readOnlys = setBit(readOnlys, " + all.get(i).nameAsConstant() + "_INDEX);");

                wl("            _readOnlys = readOnlys;");
            }

            wl("        }");
        }

        wl();
        wl("        public Version(int length)" + (_gen.isCSharp() ? "" : " {"));

        if (_gen.isCSharp()) {
            wl("            : base(length)");
            wl("        {");
        } else
            wl("            super(length);");

        wl("        }");
        wl();

        String s = _gen.isCSharp() ? "GetField" : "field";

        if (_gen.isJava())
            wl("        @Override");

        wl("        public" + _gen.target().overrideString() + _gen.target().stringString() + " getFieldName(int index) {");
        wl("            return " + s + "Name(index);");
        wl("        }");
        wl();

        if (_gen.isJava())
            wl("        @Override");

        wl("        public" + _gen.target().overrideString() + "org.objectfabric.TType getFieldType(int index) {");
        wl("            return " + s + "Type(index);");
        wl("        }");
        wl();

        if (_gen.isJava())
            wl("        @Override");

        wl("        public" + _gen.target().overrideString() + _gen.target().objectString() + " getAsObject(int index) {");
        wl("            switch (index) {");

        for (int i = 0; i < _valueSet.values().size(); i++) {
            ValueDef value = _valueSet.value(i);
            wl("                case " + value.nameAsConstant() + "_INDEX:");
            wl("                    return _" + value.Name + ";");
        }

        wl("                default:");
        wl("                    return " + (_gen.isCSharp() ? "base" : "super") + ".getAsObject(index);");
        wl("            }");
        wl("        }");
        wl();

        if (_gen.isJava())
            wl("        @Override");

        wl("        public" + _gen.target().overrideString() + "void setAsObject(int index, " + _gen.target().objectString() + " value) {");
        wl("            switch (index) {");

        for (int i = 0; i < _valueSet.values().size(); i++) {
            ValueDef value = _valueSet.value(i);
            wl("                case " + value.nameAsConstant() + "_INDEX:");

            Immutable immutable = value.type().immutable();
            String rightPart;

            if (_gen.isJava() && immutable != null && immutable.isPrimitive() && !immutable.isBoxed())
                rightPart = "(" + value.type().cast(_gen) + "value)." + immutable.java() + "Value()";
            else
                rightPart = value.type().cast(_gen) + "value";

            wl("                    _" + value.Name + " = " + rightPart + ";");
            wl("                    break;");
        }

        wl("                default:");
        wl("                    " + (_gen.isCSharp() ? "base" : "super") + ".setAsObject(index, value);");
        wl("                    break;");
        wl("            }");
        wl("        }");
        wl();

        if (_gen.isJava())
            wl("        @Override");

        wl("        public" + _gen.target().overrideString() + "void merge(" + version() + " next) {");

        if (_valueSet.values().size() > 0) {
            wl("            " + _valueSet.actualName(_gen.objectModel()) + ".Version source = (" + _valueSet.actualName(_gen.objectModel()) + ".Version) next;");
            wl();
            wl("            if (source.hasBits()) {");
        }

        for (int i = 0; i < _valueSet.values().size(); i++) {
            if (i != 0)
                wl();

            ValueDef value = _valueSet.value(i);
            wl("                if (source.getBit(" + value.nameAsConstant() + "_INDEX))");
            wl("                    _" + value.Name + " = source._" + value.Name + ";");
        }

        if (_valueSet.values().size() > 0) {
            wl("            }");
            wl();
        }

        wl("            super.merge(next);");
        wl("        }");

        if (hasReadOnlys) {
            wl();

            if (_gen.isJava())
                wl("        @Override");

            if (_valueSet.lessOr32Fields(_gen.objectModel()))
                wl("        public" + _gen.target().overrideString() + "int getReadOnlys() {");
            else
                wl("        public" + _gen.target().overrideString() + "org.objectfabric.misc.Bits.Entry[] getReadOnlys() {");

            wl("            return _readOnlys;");
            wl("        }");
        }

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

    String version() {
        String version = "org.objectfabric.TObject.Version";

        if (_gen.isCSharp()) {
            if (_valueSet.lessOr32Fields(_gen.objectModel()))
                version = "ObjectFabric.TIndexed.Version32";
            else
                version = "ObjectFabric.TIndexed.VersionN";
        }

        return version;
    }

    String getClassId() {
        String id;

        if (_valueSet instanceof ClassDef) {
            int index = _gen.objectModel().allClasses().indexOf(_valueSet);
            id = _gen.objectModel().allClassIds().get(index);
        } else {
            int index = _gen.objectModel().allMethods().indexOf(_valueSet);
            id = _gen.objectModel().allMethodIds().get(index);
        }

        return id;
    }

    private void writeSerialization() {
        wl();

        if (_gen.isJava())
            wl("        @Override");

        wl("        public" + _gen.target().overrideString() + "void writeWrite(" + (_gen.isCSharp() ? "object" : "org.objectfabric.Writer") + " writer, int index) {");

        String writerObj = _gen.isJava() ? "writer." : "";
        String writerArg = _gen.isJava() ? "" : "writer";
        String writerArgC = _gen.isJava() ? "" : "writer, ";

        wl("            if (" + writerObj + "interrupted(" + writerArg + "))");
        wl("                " + writerObj + "resume(" + writerArg + ");");
        wl();
        wl("            switch (index) {");

        for (int i = 0; i < _valueSet.values().size(); i++) {
            ValueDef value = _valueSet.value(i);
            boolean fixedLength = value.type().fixedLength();

            wl("                case " + value.nameAsConstant() + "_INDEX: {");

            if (fixedLength) {
                String canWrite = null;

                Immutable immutable = value.type().immutable();

                if (immutable == null)
                    if (value.type().customUnderlyingImmutable() != null)
                        immutable = value.type().customUnderlyingImmutable();

                if (immutable != null)
                    canWrite = "canWrite" + immutable + "(" + writerArg + ")";

                if (value.type().isJavaEnum())
                    canWrite = "canWriteInteger(" + writerArg + ")";

                wl("                    if (!" + writerObj + canWrite + ") {");
                wl("                        " + writerObj + "interrupt(" + writerArgC + "null);");
                wl("                        return;");
                wl("                    }");
                wl();
            }

            String write;

            if (value.type().immutable() != null)
                write = "write" + value.type().immutable() + "(" + writerArgC + "_" + value.Name + ")";
            else if (value.type().custom() != null) {
                Immutable immutable = value.type().customUnderlyingImmutable();
                String cast = "(" + (_gen.isJava() ? immutable.java() : immutable.csharp()) + ")";
                write = "write" + immutable + "(" + writerArgC + cast + " _" + value.Name + ")";
            } else if (value.type().isTObject())
                write = "writeTObject(" + writerArgC + "_" + value.Name + ")";
            else if (value.type().isJavaEnum())
                write = "writeInteger(" + writerArgC + "_" + value.Name + ".ordinal())";
            else
                write = "writeObject(" + writerArgC + "_" + value.Name + ")";

            wl("                    " + writerObj + write + ";");

            if (!fixedLength) {
                wl();
                wl("                    if (" + writerObj + "interrupted(" + writerArg + ")) {");
                wl("                        " + writerObj + "interrupt(" + writerArgC + "null);");
                wl("                        return;");
                wl("                    }");
                wl();
            }

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

        wl("                default: {");
        wl("                    " + (_gen.isCSharp() ? "base" : "super") + ".writeWrite(writer, index);");
        wl();
        wl("                    if (" + writerObj + "interrupted(" + writerArg + ")) {");
        wl("                        " + writerObj + "interrupt(" + writerArgC + "null);");
        wl("                        return;");
        wl("                    }");
        wl();
        wl("                    break;");
        wl("                }");
        wl("            }");
        wl("        }");
        wl();

        if (_gen.isJava())
            wl("        @Override");

        wl("        public" + _gen.target().overrideString() + "void readWrite(" + (_gen.isCSharp() ? "object" : "org.objectfabric.Reader") + " reader, int index, java.lang.Object[] versions) {");

        String readerObj = _gen.isJava() ? "reader." : "";
        String readerArg = _gen.isJava() ? "" : "reader";
        String readerArgC = _gen.isJava() ? "" : "reader, ";

        wl("            if (" + readerObj + "interrupted(" + readerArg + "))");
        wl("                " + readerObj + "resume(" + readerArg + ");");
        wl();
        wl("            switch (index) {");

        for (int i = 0; i < _valueSet.values().size(); i++) {
            ValueDef value = _valueSet.value(i);
            boolean fixedLength = value.type().fixedLength();

            wl("                case " + value.nameAsConstant() + "_INDEX: {");

            if (fixedLength) {
                String canRead = null;

                Immutable immutable = value.type().immutable();

                if (immutable == null)
                    if (value.type().customUnderlyingImmutable() != null)
                        immutable = value.type().customUnderlyingImmutable();

                if (immutable != null)
                    canRead = "canRead" + immutable + "(" + readerArg + ")";

                if (value.type().isJavaEnum())
                    canRead = "canReadInteger()";

                wl("                    if (!" + readerObj + canRead + ") {");
                wl("                        " + readerObj + "interrupt(" + readerArgC + "null);");
                wl("                        return;");
                wl("                    }");
                wl();
            }

            String left = value.type().fullName(_gen.target());
            String right;

            if (value.type().immutable() != null)
                right = readerObj + "read" + value.type().immutable() + "(" + readerArg + ")";
            else if (value.type().custom() != null) {
                Immutable immutable = value.type().customUnderlyingImmutable();
                String cast = "(" + value.type().custom() + ") ";
                right = cast + readerObj + "read" + immutable + "(" + readerArg + ")";
            } else if (value.type().isTObject()) {
                left = "java.lang.Object";
                right = readerObj + "readTObject(" + readerArg + ")";
            } else if (value.type().isJavaEnum())
                right = ObjectModelDef.formatAsConstant(value.type().fullName(Target.JAVA)) + TypeDef.ENUM_VALUES_ARRAY + "[" + readerObj + "readInteger(" + readerArg + ")]";
            else
                right = readerObj + "readObject(" + readerArg + ")";

            wl("                    " + left + " value = " + right + ";");

            if (!fixedLength) {
                wl();
                wl("                    if (" + readerObj + "interrupted(" + readerArg + ")) {");
                wl("                        " + readerObj + "interrupt(" + readerArgC + "null);");
                wl("                        return;");
                wl("                    }");
            }

            wl();

            if (value.type().canBeTObject()) {
                wl("                    for (int i = versions.length - 1; i >= 0; i--) {");
                wl("                        java.lang.Object v = value instanceof org.objectfabric.TObject[] ? ((org.objectfabric.TObject[]) value)[i] : value;");
                wl("                        ((Version) versions[i])._" + value.Name + " = (" + value.type().fullName(_gen.target()) + ") v;");
                wl("                    }");
            } else {
                wl("                    for (int i = versions.length - 1; i >= 0; i--)");
                wl("                        ((Version) versions[i])._" + value.Name + " = value;");
            }

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

        wl("                default: {");
        wl("                    " + (_gen.isCSharp() ? "base" : "super") + ".readWrite(reader, index, versions);");
        wl();
        wl("                    if (" + readerObj + "interrupted(" + readerArg + ")) {");
        wl("                        " + readerObj + "interrupt(" + readerArgC + "null);");
        wl("                        return;");
        wl("                    }");
        wl();
        wl("                    break;");
        wl("                }");
        wl("            }");
        wl("        }");
    }

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

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

    private void tab() {
        _file.tab();
    }

    private void untab() {
        _file.untab();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy