uk.co.real_logic.sbe.generation.common.PrecedenceChecks Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sbe-all Show documentation
Show all versions of sbe-all Show documentation
FIX/SBE - OSI layer 6 presentation for encoding and decoding application messages in binary format for low-latency applications.
/*
* Copyright 2013-2024 Real Logic Limited.
*
* 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
*
* https://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 uk.co.real_logic.sbe.generation.common;
import uk.co.real_logic.sbe.ir.Token;
import java.util.ArrayList;
import java.util.List;
import java.util.OptionalInt;
import java.util.function.Function;
import java.util.stream.IntStream;
import static java.util.Objects.requireNonNull;
import static uk.co.real_logic.sbe.ir.GenerationUtil.collectFields;
import static uk.co.real_logic.sbe.ir.GenerationUtil.collectGroups;
import static uk.co.real_logic.sbe.ir.GenerationUtil.collectVarData;
/**
* A factory for creating a {@link FieldPrecedenceModel} for a message from its IR tokens.
*/
public final class PrecedenceChecks
{
private static final Function SELECT_LATEST_VERSION_ONLY = versions ->
{
final OptionalInt max = versions.max();
return max.isPresent() ? IntStream.of(max.getAsInt()) : IntStream.empty();
};
private final Context context;
private PrecedenceChecks(final Context context)
{
context.conclude();
this.context = context;
}
/**
* Creates a {@link FieldPrecedenceModel} for the given message tokens,
* unless precedence checks are disabled, in which case {@code null} is returned.
*
* Only the latest version of the message is considered when creating the model.
*
*
* @param stateClassName the name of the generated class that models the state of the encoder.
* @param msgTokens the tokens of the message.
* @return a {@link FieldPrecedenceModel} for the given message tokens or {@code null} if precedence checks
* are disabled.
*/
public FieldPrecedenceModel createEncoderModel(
final String stateClassName,
final List msgTokens)
{
return createModel(stateClassName, msgTokens, SELECT_LATEST_VERSION_ONLY);
}
/**
* Creates a {@link FieldPrecedenceModel} for the given message tokens,
* unless precedence checks are disabled, in which case {@code null} is returned.
*
* All versions of the message are considered when creating the model.
*
*
* @param stateClassName the name of the generated class that models the state of the decoder.
* @param msgTokens the tokens of the message.
* @return a {@link FieldPrecedenceModel} for the given message tokens or {@code null} if precedence checks
* are disabled.
*/
public FieldPrecedenceModel createDecoderModel(
final String stateClassName,
final List msgTokens)
{
return createModel(stateClassName, msgTokens, Function.identity());
}
/**
* Creates a {@link FieldPrecedenceModel} for the given message tokens,
* unless precedence checks are disabled, in which case {@code null} is returned.
*
* All versions of the message are considered when creating the model.
*
*
* @param stateClassName the name of the generated class that models the state of the codec.
* @param msgTokens the tokens of the message.
* @return a {@link FieldPrecedenceModel} for the given message tokens or {@code null} if precedence checks
* are disabled.
*/
public FieldPrecedenceModel createCodecModel(
final String stateClassName,
final List msgTokens
)
{
return createModel(stateClassName, msgTokens, Function.identity());
}
/**
* Returns the {@link Context} describing how precedence checks should be generated.
*
* @return the {@link Context} describing how precedence checks should be generated.
*/
public Context context()
{
return context;
}
/**
* Creates a new {@link PrecedenceChecks} instance.
*
* @param context the {@link Context} describing how precedence checks should be generated.
* @return a new {@link PrecedenceChecks} instance.
*/
public static PrecedenceChecks newInstance(final Context context)
{
return new PrecedenceChecks(context);
}
private FieldPrecedenceModel createModel(
final String stateClassName,
final List tokens,
final Function versionsSelector
)
{
if (context.shouldGeneratePrecedenceChecks())
{
final Token msgToken = tokens.get(0);
final List messageBody = tokens.subList(1, tokens.size() - 1);
int i = 0;
final List fields = new ArrayList<>();
i = collectFields(messageBody, i, fields);
final List groups = new ArrayList<>();
i = collectGroups(messageBody, i, groups);
final List varData = new ArrayList<>();
collectVarData(messageBody, i, varData);
return FieldPrecedenceModel.newInstance(
stateClassName,
msgToken,
fields,
groups,
varData,
versionsSelector);
}
return null;
}
/**
* The context describing how precedence checks should be generated.
*/
public static final class Context
{
private boolean shouldGeneratePrecedenceChecks;
private String precedenceChecksFlagName = "SBE_ENABLE_PRECEDENCE_CHECKS";
private String precedenceChecksPropName = "sbe.enable.precedence.checks";
/**
* Returns {@code true} if precedence checks should be generated; {@code false} otherwise.
*
* @return {@code true} if precedence checks should be generated; {@code false} otherwise.
*/
public boolean shouldGeneratePrecedenceChecks()
{
return shouldGeneratePrecedenceChecks;
}
/**
* Sets whether field precedence checks should be generated.
*
* @param shouldGeneratePrecedenceChecks {@code true} if precedence checks should be generated;
* {@code false} otherwise.
* @return this {@link Context} instance.
*/
public Context shouldGeneratePrecedenceChecks(final boolean shouldGeneratePrecedenceChecks)
{
this.shouldGeneratePrecedenceChecks = shouldGeneratePrecedenceChecks;
return this;
}
/**
* Returns the name of the flag that can be used to enable precedence checks at runtime.
*
* @return the name of the flag that can be used to enable precedence checks at runtime.
*/
public String precedenceChecksFlagName()
{
return precedenceChecksFlagName;
}
/**
* Sets the name of the flag that can be used to enable precedence checks at runtime.
*
* @param precedenceChecksFlagName the name of the flag that can be used to enable
* precedence checks at runtime.
* @return this {@link Context} instance.
*/
public Context precedenceChecksFlagName(final String precedenceChecksFlagName)
{
this.precedenceChecksFlagName = precedenceChecksFlagName;
return this;
}
/**
* Returns the name of the system property that can be used to enable precedence checks
* at runtime.
*
* @return the name of the system property that can be used to enable precedence checks
* at runtime.
*/
public String precedenceChecksPropName()
{
return precedenceChecksPropName;
}
/**
* Sets the name of the system property that can be used to enable precedence checks
* at runtime.
*
* @param precedenceChecksPropName the name of the system property that can be used to
* enable precedence checks at runtime.
* @return this {@link Context} instance.
*/
public Context precedenceChecksPropName(final String precedenceChecksPropName)
{
this.precedenceChecksPropName = precedenceChecksPropName;
return this;
}
/**
* Validates this {@link Context} instance.
*/
public void conclude()
{
requireNonNull(precedenceChecksFlagName, "precedenceChecksFlagName");
requireNonNull(precedenceChecksPropName, "precedenceChecksPropName");
}
}
}