kafka VersionConditional 源码

  • 2022-10-20
  • 浏览 (230)

kafka VersionConditional 代码

文件路径:/generator/src/main/java/org/apache/kafka/message/VersionConditional.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.kafka.message;

/**
 * Creates an if statement based on whether or not the current version
 * falls within a given range.
 */
public final class VersionConditional {
    /**
     * Create a version conditional.
     *
     * @param containingVersions    The versions for which the conditional is true.
     * @param possibleVersions      The range of possible versions.
     * @return                      The version conditional.
     */
    static VersionConditional forVersions(Versions containingVersions,
                                          Versions possibleVersions) {
        return new VersionConditional(containingVersions, possibleVersions);
    }

    private final Versions containingVersions;
    private final Versions possibleVersions;
    private ClauseGenerator ifMember = null;
    private ClauseGenerator ifNotMember = null;
    private boolean alwaysEmitBlockScope = false;
    private boolean allowMembershipCheckAlwaysFalse = true;

    private VersionConditional(Versions containingVersions, Versions possibleVersions) {
        this.containingVersions = containingVersions;
        this.possibleVersions = possibleVersions;
    }

    VersionConditional ifMember(ClauseGenerator ifMember) {
        this.ifMember = ifMember;
        return this;
    }

    VersionConditional ifNotMember(ClauseGenerator ifNotMember) {
        this.ifNotMember = ifNotMember;
        return this;
    }

    /**
     * If this is set, we will always create a new block scope, even if there
     * are no 'if' statements.  This is useful for cases where we want to
     * declare variables in the clauses without worrying if they conflict with
     * other variables of the same name.
     */
    VersionConditional alwaysEmitBlockScope(boolean alwaysEmitBlockScope) {
        this.alwaysEmitBlockScope = alwaysEmitBlockScope;
        return this;
    }

    /**
     * If this is set, VersionConditional#generate will throw an exception if
     * the 'ifMember' clause is never used.  This is useful as a sanity check
     * in some cases where it doesn't make sense for the condition to always be
     * false.  For example, when generating a Message#write function, 
     * we might check that the version we're writing is supported.  It wouldn't
     * make sense for this check to always be false, since that would mean that
     * no versions at all were supported.
     */
    VersionConditional allowMembershipCheckAlwaysFalse(boolean allowMembershipCheckAlwaysFalse) {
        this.allowMembershipCheckAlwaysFalse = allowMembershipCheckAlwaysFalse;
        return this;
    }

    private void generateFullRangeCheck(Versions ifVersions,
                                        Versions ifNotVersions,
                                        CodeBuffer buffer) {
        if (ifMember != null) {
            buffer.printf("if ((_version >= %d) && (_version <= %d)) {%n",
                    containingVersions.lowest(), containingVersions.highest());
            buffer.incrementIndent();
            ifMember.generate(ifVersions);
            buffer.decrementIndent();
            if (ifNotMember != null) {
                buffer.printf("} else {%n");
                buffer.incrementIndent();
                ifNotMember.generate(ifNotVersions);
                buffer.decrementIndent();
            }
            buffer.printf("}%n");
        } else if (ifNotMember != null) {
            buffer.printf("if ((_version < %d) || (_version > %d)) {%n",
                    containingVersions.lowest(), containingVersions.highest());
            buffer.incrementIndent();
            ifNotMember.generate(ifNotVersions);
            buffer.decrementIndent();
            buffer.printf("}%n");
        }
    }

    private void generateLowerRangeCheck(Versions ifVersions,
                                         Versions ifNotVersions,
                                         CodeBuffer buffer) {
        if (ifMember != null) {
            buffer.printf("if (_version >= %d) {%n", containingVersions.lowest());
            buffer.incrementIndent();
            ifMember.generate(ifVersions);
            buffer.decrementIndent();
            if (ifNotMember != null) {
                buffer.printf("} else {%n");
                buffer.incrementIndent();
                ifNotMember.generate(ifNotVersions);
                buffer.decrementIndent();
            }
            buffer.printf("}%n");
        } else if (ifNotMember != null) {
            buffer.printf("if (_version < %d) {%n", containingVersions.lowest());
            buffer.incrementIndent();
            ifNotMember.generate(ifNotVersions);
            buffer.decrementIndent();
            buffer.printf("}%n");
        }
    }

    private void generateUpperRangeCheck(Versions ifVersions,
                                         Versions ifNotVersions,
                                         CodeBuffer buffer) {
        if (ifMember != null) {
            buffer.printf("if (_version <= %d) {%n", containingVersions.highest());
            buffer.incrementIndent();
            ifMember.generate(ifVersions);
            buffer.decrementIndent();
            if (ifNotMember != null) {
                buffer.printf("} else {%n");
                buffer.incrementIndent();
                ifNotMember.generate(ifNotVersions);
                buffer.decrementIndent();
            }
            buffer.printf("}%n");
        } else if (ifNotMember != null) {
            buffer.printf("if (_version > %d) {%n", containingVersions.highest());
            buffer.incrementIndent();
            ifNotMember.generate(ifNotVersions);
            buffer.decrementIndent();
            buffer.printf("}%n");
        }
    }

    private void generateAlwaysTrueCheck(Versions ifVersions, CodeBuffer buffer) {
        if (ifMember != null) {
            if (alwaysEmitBlockScope) {
                buffer.printf("{%n");
                buffer.incrementIndent();
            }
            ifMember.generate(ifVersions);
            if (alwaysEmitBlockScope) {
                buffer.decrementIndent();
                buffer.printf("}%n");
            }
        }
    }

    private void generateAlwaysFalseCheck(Versions ifNotVersions, CodeBuffer buffer) {
        if (!allowMembershipCheckAlwaysFalse) {
            throw new RuntimeException("Version ranges " + containingVersions +
                " and " + possibleVersions + " have no versions in common.");
        }
        if (ifNotMember != null) {
            if (alwaysEmitBlockScope) {
                buffer.printf("{%n");
                buffer.incrementIndent();
            }
            ifNotMember.generate(ifNotVersions);
            if (alwaysEmitBlockScope) {
                buffer.decrementIndent();
                buffer.printf("}%n");
            }
        }
    }

    void generate(CodeBuffer buffer) {
        Versions ifVersions = possibleVersions.intersect(containingVersions);
        Versions ifNotVersions = possibleVersions.subtract(containingVersions);
        // In the case where ifNotVersions would be two ranges rather than one,
        // we just pass in the original possibleVersions instead.
        // This is slightly less optimal, but allows us to avoid dealing with
        // multiple ranges.
        if (ifNotVersions == null) {
            ifNotVersions = possibleVersions;
        }

        if (possibleVersions.lowest() < containingVersions.lowest()) {
            if (possibleVersions.highest() > containingVersions.highest()) {
                generateFullRangeCheck(ifVersions, ifNotVersions, buffer);
            } else if (possibleVersions.highest() >= containingVersions.lowest()) {
                generateLowerRangeCheck(ifVersions, ifNotVersions, buffer);
            } else {
                generateAlwaysFalseCheck(ifNotVersions, buffer);
            }
        } else if (possibleVersions.highest() >= containingVersions.lowest() &&
                    (possibleVersions.lowest() <= containingVersions.highest())) {
            if (possibleVersions.highest() > containingVersions.highest()) {
                generateUpperRangeCheck(ifVersions, ifNotVersions, buffer);
            } else {
                generateAlwaysTrueCheck(ifVersions, buffer);
            }
        } else {
            generateAlwaysFalseCheck(ifNotVersions, buffer);
        }
    }
}

相关信息

kafka 源码目录

相关文章

kafka ApiMessageTypeGenerator 源码

kafka ClauseGenerator 源码

kafka CodeBuffer 源码

kafka EntityType 源码

kafka FieldSpec 源码

kafka FieldType 源码

kafka HeaderGenerator 源码

kafka IsNullConditional 源码

kafka JsonConverterGenerator 源码

kafka MessageClassGenerator 源码

0  赞