mirror of https://github.com/rusefi/rusefi-1.git
global static variable bad, dependency injection better
This commit is contained in:
parent
d2f54daefd
commit
b5c122408c
|
@ -236,19 +236,19 @@ public class ConfigDefinition {
|
|||
SystemOut.println(state.enumsReader.getEnums() + " total enumsReader");
|
||||
}
|
||||
|
||||
long crc32 = signatureHash(tsPath, inputAllFiles);
|
||||
long crc32 = signatureHash(state, tsPath, inputAllFiles);
|
||||
|
||||
handleFiringOrder(firingEnumFileName);
|
||||
handleFiringOrder(firingEnumFileName, state.variableRegistry);
|
||||
|
||||
MESSAGE = getGeneratedAutomaticallyTag() + definitionInputFile + " " + new Date();
|
||||
|
||||
SystemOut.println("Reading definition from " + definitionInputFile);
|
||||
|
||||
for (String prependFile : prependFiles)
|
||||
readPrependValues(VariableRegistry.INSTANCE, prependFile);
|
||||
readPrependValues(state.variableRegistry, prependFile);
|
||||
|
||||
if (yamlFiles != null) {
|
||||
processYamls(VariableRegistry.INSTANCE, yamlFiles, state);
|
||||
processYamls(state.variableRegistry, yamlFiles, state);
|
||||
}
|
||||
|
||||
// Parse the input files
|
||||
|
@ -304,7 +304,7 @@ public class ConfigDefinition {
|
|||
}
|
||||
if (needToUpdateOtherFiles) {
|
||||
if (destCHeaderFileName != null) {
|
||||
destinations.add(new CHeaderConsumer(destCHeaderFileName));
|
||||
destinations.add(new CHeaderConsumer(state.variableRegistry, destCHeaderFileName));
|
||||
}
|
||||
if (javaDestinationFileName != null) {
|
||||
destinations.add(new FileJavaFieldsConsumer(state, javaDestinationFileName));
|
||||
|
@ -329,19 +329,19 @@ public class ConfigDefinition {
|
|||
|
||||
|
||||
if (destCDefinesFileName != null && needToUpdateOtherFiles)
|
||||
VariableRegistry.INSTANCE.writeDefinesToFile(destCDefinesFileName);
|
||||
state.variableRegistry.writeDefinesToFile(destCDefinesFileName);
|
||||
|
||||
if (romRaiderDestination != null && romRaiderInputFile != null && needToUpdateOtherFiles) {
|
||||
processTextTemplate(romRaiderInputFile, romRaiderDestination);
|
||||
processTextTemplate(state, romRaiderInputFile, romRaiderDestination);
|
||||
}
|
||||
|
||||
CachingStrategy.saveCachedInputFiles(inputAllFiles, cachePath, cacheZipFile);
|
||||
}
|
||||
|
||||
private static void handleFiringOrder(String firingEnumFileName) throws IOException {
|
||||
private static void handleFiringOrder(String firingEnumFileName, VariableRegistry variableRegistry) throws IOException {
|
||||
if (firingEnumFileName != null) {
|
||||
SystemOut.println("Reading firing from " + firingEnumFileName);
|
||||
VariableRegistry.INSTANCE.register("FIRINGORDER", FiringOrderTSLogic.invoke(firingEnumFileName));
|
||||
variableRegistry.register("FIRINGORDER", FiringOrderTSLogic.invoke(firingEnumFileName));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,7 +352,7 @@ public class ConfigDefinition {
|
|||
}
|
||||
}
|
||||
|
||||
private static long signatureHash(String tsPath, List<String> inputAllFiles) throws IOException {
|
||||
private static long signatureHash(ReaderState state, String tsPath, List<String> inputAllFiles) throws IOException {
|
||||
// get CRC32 of given input files
|
||||
long crc32 = 0;
|
||||
for (String iFile : inputAllFiles) {
|
||||
|
@ -363,7 +363,7 @@ public class ConfigDefinition {
|
|||
SystemOut.println("CRC32 from all input files = " + crc32);
|
||||
// store the CRC32 as a built-in variable
|
||||
if (tsPath != null) // nasty trick - do not insert signature into live data files
|
||||
VariableRegistry.INSTANCE.register(SIGNATURE_HASH, "" + crc32);
|
||||
state.variableRegistry.register(SIGNATURE_HASH, "" + crc32);
|
||||
return crc32;
|
||||
}
|
||||
|
||||
|
@ -520,11 +520,11 @@ public class ConfigDefinition {
|
|||
}
|
||||
}
|
||||
|
||||
private static void processTextTemplate(String inputFileName, String outputFileName) throws IOException {
|
||||
private static void processTextTemplate(ReaderState state, String inputFileName, String outputFileName) throws IOException {
|
||||
SystemOut.println("Reading from " + inputFileName);
|
||||
SystemOut.println("Writing to " + outputFileName);
|
||||
|
||||
VariableRegistry.INSTANCE.put("generator_message", ConfigDefinition.getGeneratedAutomaticallyTag() + new Date());
|
||||
state.variableRegistry.put("generator_message", ConfigDefinition.getGeneratedAutomaticallyTag() + new Date());
|
||||
|
||||
File inputFile = new File(inputFileName);
|
||||
|
||||
|
@ -533,7 +533,7 @@ public class ConfigDefinition {
|
|||
|
||||
String line;
|
||||
while ((line = fr.readLine()) != null) {
|
||||
line = VariableRegistry.INSTANCE.applyVariables(line);
|
||||
line = state.variableRegistry.applyVariables(line);
|
||||
fw.write(line + ConfigDefinition.EOL);
|
||||
}
|
||||
fw.close();
|
||||
|
@ -572,9 +572,9 @@ public class ConfigDefinition {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static int getSize(String s) {
|
||||
if (VariableRegistry.INSTANCE.intValues.containsKey(s)) {
|
||||
return VariableRegistry.INSTANCE.intValues.get(s);
|
||||
public static int getSize(VariableRegistry variableRegistry, String s) {
|
||||
if (variableRegistry.intValues.containsKey(s)) {
|
||||
return variableRegistry.intValues.get(s);
|
||||
}
|
||||
return Integer.parseInt(s);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ public class ConfigField {
|
|||
this.type = type;
|
||||
this.arraySizeVariableName = arraySizeAsText;
|
||||
this.arraySize = arraySize;
|
||||
this.tsInfo = VariableRegistry.INSTANCE.applyVariables(tsInfo);
|
||||
this.tsInfo = tsInfo == null ? null : state.variableRegistry.applyVariables(tsInfo);
|
||||
this.isIterate = isIterate;
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ public class ConfigField {
|
|||
String arraySizeAsText;
|
||||
if (matcher.group(3) != null) {
|
||||
arraySizeAsText = matcher.group(3);
|
||||
arraySize = ConfigDefinition.getSize(arraySizeAsText);
|
||||
arraySize = ConfigDefinition.getSize(state.variableRegistry, arraySizeAsText);
|
||||
} else {
|
||||
arraySize = 1;
|
||||
arraySizeAsText = null;
|
||||
|
|
|
@ -26,12 +26,13 @@ public class ReaderState {
|
|||
private static final String STRUCT = "struct ";
|
||||
private static final String DEFINE_CONSTRUCTOR = "define_constructor";
|
||||
public static final char MULT_TOKEN = '*';
|
||||
public Stack<ConfigStructure> stack = new Stack<>();
|
||||
public Map<String, Integer> tsCustomSize = new HashMap<>();
|
||||
public Map<String, String> tsCustomLine = new HashMap<>();
|
||||
public Map<String, ConfigStructure> structures = new HashMap<>();
|
||||
public final Stack<ConfigStructure> stack = new Stack<>();
|
||||
public final Map<String, Integer> tsCustomSize = new HashMap<>();
|
||||
public final Map<String, String> tsCustomLine = new HashMap<>();
|
||||
public final Map<String, ConfigStructure> structures = new HashMap<>();
|
||||
|
||||
public EnumsReader enumsReader = new EnumsReader();
|
||||
public final EnumsReader enumsReader = new EnumsReader();
|
||||
public final VariableRegistry variableRegistry = new VariableRegistry();
|
||||
|
||||
private static void handleBitLine(ReaderState state, String line) {
|
||||
line = line.substring(BIT.length() + 1).trim();
|
||||
|
@ -66,14 +67,14 @@ public class ReaderState {
|
|||
return line.length() == 0 || line.startsWith("!") || line.startsWith("//");
|
||||
}
|
||||
|
||||
private static void handleCustomLine(ReaderState state, String line) {
|
||||
private void handleCustomLine(ReaderState state, String line) {
|
||||
line = line.substring(CUSTOM.length() + 1).trim();
|
||||
int index = line.indexOf(' ');
|
||||
String name = line.substring(0, index);
|
||||
|
||||
String autoEnumOptions = VariableRegistry.INSTANCE.getEnumOptionsForTunerStudio(state.enumsReader, name);
|
||||
String autoEnumOptions = state.variableRegistry.getEnumOptionsForTunerStudio(state.enumsReader, name);
|
||||
if (autoEnumOptions != null) {
|
||||
VariableRegistry.INSTANCE.register(name + "_auto_enum", autoEnumOptions);
|
||||
state.variableRegistry.register(name + "_auto_enum", autoEnumOptions);
|
||||
}
|
||||
|
||||
line = line.substring(index).trim();
|
||||
|
@ -81,7 +82,7 @@ public class ReaderState {
|
|||
String customSize = line.substring(0, index);
|
||||
|
||||
String tunerStudioLine = line.substring(index).trim();
|
||||
tunerStudioLine = VariableRegistry.INSTANCE.applyVariables(tunerStudioLine);
|
||||
tunerStudioLine = state.variableRegistry.applyVariables(tunerStudioLine);
|
||||
int size = parseSize(customSize, line);
|
||||
state.tsCustomSize.put(name, size);
|
||||
|
||||
|
@ -105,10 +106,10 @@ public class ReaderState {
|
|||
state.tsCustomLine.put(name, tunerStudioLine);
|
||||
}
|
||||
|
||||
public static int parseSize(String customSize, String line) {
|
||||
customSize = VariableRegistry.INSTANCE.applyVariables(customSize);
|
||||
public int parseSize(String customSize, String line) {
|
||||
customSize = variableRegistry.applyVariables(customSize);
|
||||
customSize = customSize.replaceAll("x", "*");
|
||||
line = VariableRegistry.INSTANCE.applyVariables(line);
|
||||
line = variableRegistry.applyVariables(line);
|
||||
|
||||
int multPosition = customSize.indexOf(MULT_TOKEN);
|
||||
if (multPosition != -1) {
|
||||
|
@ -175,7 +176,7 @@ public class ReaderState {
|
|||
* for example
|
||||
* #define CLT_CURVE_SIZE 16
|
||||
*/
|
||||
ConfigDefinition.processDefine(VariableRegistry.INSTANCE, line.substring(DEFINE.length()).trim());
|
||||
ConfigDefinition.processDefine(variableRegistry, line.substring(DEFINE.length()).trim());
|
||||
} else {
|
||||
if (stack.isEmpty())
|
||||
throw new IllegalStateException("Expected to be within structure at line " + lineIndex + ": " + line);
|
||||
|
|
|
@ -229,12 +229,6 @@ public class VariableRegistry {
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
data.clear();
|
||||
cAllDefinitions.clear();
|
||||
javaDefinitions.clear();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return data.size();
|
||||
}
|
||||
|
|
|
@ -18,8 +18,10 @@ public class CHeaderConsumer extends BaseCHeaderConsumer {
|
|||
*/
|
||||
public static boolean withC_Defines;
|
||||
private final LazyFile cHeader;
|
||||
private final VariableRegistry variableRegistry;
|
||||
|
||||
public CHeaderConsumer(String destCHeader) {
|
||||
public CHeaderConsumer(VariableRegistry variableRegistry, String destCHeader) {
|
||||
this.variableRegistry = variableRegistry;
|
||||
SystemOut.println("Writing C header to " + destCHeader);
|
||||
cHeader = new LazyFile(destCHeader);
|
||||
cHeader.write("// this section " + ConfigDefinition.MESSAGE + EOL);
|
||||
|
@ -32,7 +34,7 @@ public class CHeaderConsumer extends BaseCHeaderConsumer {
|
|||
@Override
|
||||
public void endFile() throws IOException {
|
||||
if (withC_Defines)
|
||||
cHeader.write(VariableRegistry.INSTANCE.getDefinesSection());
|
||||
cHeader.write(variableRegistry.getDefinesSection());
|
||||
cHeader.write(getContent().toString());
|
||||
cHeader.write("// end" + EOL);
|
||||
cHeader.write("// this section " + ConfigDefinition.MESSAGE + EOL);
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.rusefi.output;
|
|||
|
||||
import com.rusefi.ConfigDefinition;
|
||||
import com.rusefi.ReaderState;
|
||||
import com.rusefi.VariableRegistry;
|
||||
import com.rusefi.util.LazyFile;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -37,7 +36,7 @@ public class FileJavaFieldsConsumer extends JavaFieldsConsumer {
|
|||
|
||||
@Override
|
||||
public void endFile() throws IOException {
|
||||
javaFields.write(VariableRegistry.INSTANCE.getJavaConstants());
|
||||
javaFields.write(state.variableRegistry.getJavaConstants());
|
||||
javaFields.write(getJavaFieldsWriter());
|
||||
|
||||
allFields.append("\t};" + EOL);
|
||||
|
|
|
@ -17,7 +17,7 @@ public abstract class JavaFieldsConsumer implements ConfigurationConsumer {
|
|||
|
||||
private final CharArrayWriter javaFieldsWriter = new CharArrayWriter();
|
||||
protected final StringBuffer allFields = new StringBuffer("\tpublic static final Field[] VALUES = {" + EOL);
|
||||
private final ReaderState state;
|
||||
protected final ReaderState state;
|
||||
|
||||
public JavaFieldsConsumer(ReaderState state) {
|
||||
this.state = state;
|
||||
|
@ -74,7 +74,7 @@ public abstract class JavaFieldsConsumer implements ConfigurationConsumer {
|
|||
writeJavaFieldName(nameWithPrefix, tsPosition);
|
||||
javaFieldsWriter.write("FieldType.FLOAT);" + EOL);
|
||||
} else {
|
||||
String enumOptions = VariableRegistry.INSTANCE.get(configField.getType() + ConfigField.ENUM_SUFFIX);
|
||||
String enumOptions = state.variableRegistry.get(configField.getType() + ConfigField.ENUM_SUFFIX);
|
||||
|
||||
if (enumOptions != null && !javaEnums.contains(configField.getType())) {
|
||||
javaEnums.add(configField.getType());
|
||||
|
|
|
@ -44,7 +44,7 @@ public class TSProjectConsumer implements ConfigurationConsumer {
|
|||
if (configField.getComment() != null && configField.getComment().startsWith(ConfigField.TS_COMMENT_TAG + "")) {
|
||||
settingContextHelp.append("\t" + nameWithPrefix + " = \"" + configField.getCommentContent() + "\"" + EOL);
|
||||
}
|
||||
VariableRegistry.INSTANCE.register(nameWithPrefix + "_offset", tsPosition);
|
||||
state.variableRegistry.register(nameWithPrefix + "_offset", tsPosition);
|
||||
|
||||
ConfigStructure cs = configField.getState().structures.get(configField.getType());
|
||||
if (cs != null) {
|
||||
|
@ -186,7 +186,7 @@ public class TSProjectConsumer implements ConfigurationConsumer {
|
|||
* rusefi.input has all the content of the future .ini file with the exception of data page
|
||||
* TODO: start generating [outputs] section as well
|
||||
*/
|
||||
private static TsFileContent readTsTemplateInputFile(String tsPath) throws IOException {
|
||||
private TsFileContent readTsTemplateInputFile(String tsPath) throws IOException {
|
||||
String fileName = getTsFileInputName(tsPath);
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), CHARSET.name()));
|
||||
|
||||
|
@ -208,20 +208,20 @@ public class TSProjectConsumer implements ConfigurationConsumer {
|
|||
|
||||
if (line.contains(TS_CONDITION)) {
|
||||
String token = getToken(line);
|
||||
String strValue = VariableRegistry.INSTANCE.get(token);
|
||||
String strValue = state.variableRegistry.get(token);
|
||||
boolean value = Boolean.parseBoolean(strValue);
|
||||
if (!value)
|
||||
continue; // skipping this line
|
||||
line = removeToken(line);
|
||||
}
|
||||
|
||||
line = VariableRegistry.INSTANCE.applyVariables(line);
|
||||
line = state.variableRegistry.applyVariables(line);
|
||||
|
||||
if (isBeforeStartTag)
|
||||
prefix.append(line + ConfigDefinition.EOL);
|
||||
|
||||
if (isAfterEndTag)
|
||||
postfix.append(VariableRegistry.INSTANCE.applyVariables(line) + ConfigDefinition.EOL);
|
||||
postfix.append(state.variableRegistry.applyVariables(line) + ConfigDefinition.EOL);
|
||||
}
|
||||
r.close();
|
||||
return new TsFileContent(prefix.toString(), postfix.toString());
|
||||
|
@ -266,11 +266,11 @@ public class TSProjectConsumer implements ConfigurationConsumer {
|
|||
|
||||
@Override
|
||||
public void handleEndStruct(ConfigStructure structure) throws IOException {
|
||||
VariableRegistry.INSTANCE.register(structure.name + "_size", structure.getTotalSize());
|
||||
state.variableRegistry.register(structure.name + "_size", structure.getTotalSize());
|
||||
if (state.stack.isEmpty()) {
|
||||
totalTsSize = writeTunerStudio(structure, "", tsWriter, 0);
|
||||
tsWriter.write("; total TS size = " + totalTsSize + EOL);
|
||||
VariableRegistry.INSTANCE.register("TOTAL_CONFIG_SIZE", totalTsSize);
|
||||
state.variableRegistry.register("TOTAL_CONFIG_SIZE", totalTsSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,6 @@ public class ConfigFieldParserTest {
|
|||
"#define ERROR_BUFFER_SIZE \"***\"\n" +
|
||||
"end_struct\n" +
|
||||
"";
|
||||
VariableRegistry.INSTANCE.clear();
|
||||
BufferedReader reader = new BufferedReader(new StringReader(test));
|
||||
new ReaderState().readBufferedReader(reader, Collections.emptyList());
|
||||
}
|
||||
|
@ -122,7 +121,6 @@ public class ConfigFieldParserTest {
|
|||
ReaderState.DEFINE + " show show_Hellen121vag_presets true\n" +
|
||||
"end_struct\n" +
|
||||
"";
|
||||
VariableRegistry.INSTANCE.clear();
|
||||
BufferedReader reader = new BufferedReader(new StringReader(test));
|
||||
new ReaderState().readBufferedReader(reader, Collections.emptyList());
|
||||
}
|
||||
|
@ -137,13 +135,13 @@ public class ConfigFieldParserTest {
|
|||
"end_struct\n" +
|
||||
"";
|
||||
|
||||
VariableRegistry.INSTANCE.clear();
|
||||
BufferedReader reader = new BufferedReader(new StringReader(test));
|
||||
new ReaderState().readBufferedReader(reader, Collections.emptyList());
|
||||
ReaderState state = new ReaderState();
|
||||
state.readBufferedReader(reader, Collections.emptyList());
|
||||
|
||||
assertEquals("#define ERROR_BUFFER_COUNT 120\n" +
|
||||
"#define ERROR_BUFFER_SIZE 120\n" +
|
||||
"#define RESULT 14400\n", VariableRegistry.INSTANCE.getDefinesSection());
|
||||
"#define RESULT 14400\n", state.variableRegistry.getDefinesSection());
|
||||
}
|
||||
@Test
|
||||
public void expressionInMultiplier() throws IOException {
|
||||
|
@ -155,7 +153,6 @@ public class ConfigFieldParserTest {
|
|||
"end_struct\n" +
|
||||
"";
|
||||
|
||||
VariableRegistry.INSTANCE.clear();
|
||||
BufferedReader reader = new BufferedReader(new StringReader(test));
|
||||
|
||||
CharArrayWriter writer = new CharArrayWriter();
|
||||
|
@ -172,7 +169,6 @@ public class ConfigFieldParserTest {
|
|||
|
||||
@Test
|
||||
public void useCustomType() throws IOException {
|
||||
VariableRegistry.INSTANCE.clear();
|
||||
ReaderState state = new ReaderState();
|
||||
String test = "struct pid_s\n" +
|
||||
"#define ERROR_BUFFER_SIZE 120\n" +
|
||||
|
@ -193,7 +189,6 @@ public class ConfigFieldParserTest {
|
|||
|
||||
@Test
|
||||
public void testDefineChar() throws IOException {
|
||||
VariableRegistry.INSTANCE.clear();
|
||||
ReaderState state = new ReaderState();
|
||||
String test =
|
||||
"#define SD_r 'r'\n" +
|
||||
|
@ -205,12 +200,11 @@ public class ConfigFieldParserTest {
|
|||
|
||||
assertEquals("\tpublic static final char SD_r = 'r';\n" +
|
||||
"",
|
||||
VariableRegistry.INSTANCE.getJavaConstants());
|
||||
state.variableRegistry.getJavaConstants());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefine() throws IOException {
|
||||
VariableRegistry.INSTANCE.clear();
|
||||
ReaderState state = new ReaderState();
|
||||
String test =
|
||||
"#define ERROR_BUFFER_SIZE 120\n" +
|
||||
|
@ -224,7 +218,7 @@ public class ConfigFieldParserTest {
|
|||
assertEquals("\tpublic static final int ERROR_BUFFER_SIZE = 120;\n" +
|
||||
"\tpublic static final int ERROR_BUFFER_SIZE_H = 0x120;\n" +
|
||||
"",
|
||||
VariableRegistry.INSTANCE.getJavaConstants());
|
||||
state.variableRegistry.getJavaConstants());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -345,7 +339,6 @@ public class ConfigFieldParserTest {
|
|||
"int[ERROR_BUFFER_SIZE iterate] field\n" +
|
||||
"end_struct\n" +
|
||||
"";
|
||||
VariableRegistry.INSTANCE.clear();
|
||||
BufferedReader reader = new BufferedReader(new StringReader(test));
|
||||
BaseCHeaderConsumer consumer = new BaseCHeaderConsumer() {
|
||||
@Override
|
||||
|
@ -414,15 +407,14 @@ public class ConfigFieldParserTest {
|
|||
|
||||
@Test
|
||||
public void testParseSize() {
|
||||
assertEquals(4, ReaderState.parseSize("4", ""));
|
||||
ReaderState state = new ReaderState();
|
||||
assertEquals(4, state.parseSize("4", ""));
|
||||
|
||||
assertEquals(12, ReaderState.parseSize("4*3", ""));
|
||||
assertEquals(12, state.parseSize("4*3", ""));
|
||||
|
||||
VariableRegistry.INSTANCE.clear();
|
||||
state.variableRegistry.register("var", 256);
|
||||
|
||||
VariableRegistry.INSTANCE.register("var", 256);
|
||||
|
||||
assertEquals(512, ReaderState.parseSize("2*@@var@@", ""));
|
||||
assertEquals(512, ReaderState.parseSize("2x@@var@@", ""));
|
||||
assertEquals(512, state.parseSize("2*@@var@@", ""));
|
||||
assertEquals(512, state.parseSize("2x@@var@@", ""));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import com.rusefi.output.TSProjectConsumer;
|
|||
import java.io.CharArrayWriter;
|
||||
|
||||
public class TestTSProjectConsumer extends TSProjectConsumer {
|
||||
public TestTSProjectConsumer(CharArrayWriter writer, String s, ReaderState state) {
|
||||
super(writer, s, state);
|
||||
public TestTSProjectConsumer(CharArrayWriter writer, String tsPath, ReaderState state) {
|
||||
super(writer, tsPath, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue