rusefi/java_console/inifile/src/main/java/com/opensr5/ini/IniFileModel.java

324 lines
10 KiB
Java
Raw Normal View History

package com.opensr5.ini;
2015-12-23 19:01:26 -08:00
2020-07-29 16:25:25 -07:00
import com.devexperts.logging.Logging;
2020-05-19 23:16:15 -07:00
import com.opensr5.ini.field.*;
2024-04-01 13:44:53 -07:00
import com.rusefi.core.FindFileHelper;
2016-01-19 21:01:29 -08:00
2015-12-23 19:01:26 -08:00
import java.io.*;
import java.util.*;
/**
2020-06-09 17:08:16 -07:00
* Andrey Belomutskiy, (c) 2013-2020
2015-12-23 19:01:26 -08:00
* 12/23/2015.
*/
public class IniFileModel {
2020-07-29 16:25:25 -07:00
private static final Logging log = Logging.getLogging(IniFileModel.class);
public static final String RUSEFI_INI_PREFIX = "rusefi";
public static final String RUSEFI_INI_SUFFIX = ".ini";
2020-05-19 23:51:14 -07:00
public static final String INI_FILE_PATH = System.getProperty("ini_file_path", "..");
2020-05-16 19:51:47 -07:00
private static final String SECTION_PAGE = "page";
private static final String FIELD_TYPE_SCALAR = "scalar";
2020-07-18 16:11:51 -07:00
public static final String FIELD_TYPE_STRING = "string";
2020-05-16 19:51:47 -07:00
private static final String FIELD_TYPE_ARRAY = "array";
private static final String FIELD_TYPE_BITS = "bits";
2015-12-23 19:01:26 -08:00
2023-11-25 15:49:17 -08:00
public Map<String, List<String>> defines = new TreeMap<>();
private static IniFileModel INSTANCE;
2016-01-19 20:02:48 -08:00
private String dialogId;
private String dialogUiName;
private final Map<String, DialogModel> dialogs = new TreeMap<>();
// this is only used while reading model - TODO extract reader
private final List<DialogModel.Field> fieldsOfCurrentDialog = new ArrayList<>();
public Map<String, IniField> allIniFields = new LinkedHashMap<>();
public final Map<String, DialogModel.Field> fieldsInUiOrder = new LinkedHashMap<>();
2015-12-23 19:01:26 -08:00
2020-04-29 19:34:51 -07:00
public Map<String, String> tooltips = new TreeMap<>();
2020-10-03 15:58:59 -07:00
public Map<String, String> protocolMeta = new TreeMap<>();
private boolean isConstantsSection;
private String currentYBins;
private String currentXBins;
private final Map<String, String> xBinsByZBins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
private final Map<String, String> yBinsByZBins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
2020-04-29 19:34:51 -07:00
2015-12-23 19:01:26 -08:00
public static void main(String[] args) {
IniFileModel iniFile = new IniFileModel();
iniFile.findAndReadIniFile(INI_FILE_PATH);
log.info("Dialogs: " + iniFile.dialogs);
2015-12-23 19:01:26 -08:00
}
2020-05-16 19:51:47 -07:00
private boolean isInSettingContextHelp = false;
private boolean isInsidePageDefinition;
2020-04-29 19:34:51 -07:00
public IniFileModel findAndReadIniFile(String iniFilePath) {
String fileName = findMetaInfoFile(iniFilePath);
return readIniFile(fileName);
2020-06-12 22:07:48 -07:00
}
public IniFileModel readIniFile(String fileName) {
File input = null;
if (fileName != null)
input = new File(fileName);
if (fileName == null || !input.exists()) {
2020-07-29 16:25:25 -07:00
log.error("No such file: " + fileName);
return null;
2015-12-23 19:01:26 -08:00
}
2020-07-29 16:25:25 -07:00
log.info("Reading " + fileName);
2017-03-01 14:13:48 -08:00
RawIniFile content = IniFileReader.read(input);
2015-12-23 19:01:26 -08:00
2020-05-16 19:51:47 -07:00
readIniFile(content);
return this;
2020-05-16 19:51:47 -07:00
}
2015-12-23 19:01:26 -08:00
2020-05-16 19:51:47 -07:00
public IniFileModel readIniFile(RawIniFile content) {
2017-03-01 14:13:48 -08:00
for (RawIniFile.Line line : content.getLines()) {
handleLine(line);
2016-01-15 20:01:43 -08:00
}
2017-03-01 14:13:48 -08:00
finishDialog();
2020-05-16 19:51:47 -07:00
return this;
2016-01-15 20:01:43 -08:00
}
2015-12-23 19:01:26 -08:00
2020-05-21 22:41:01 -07:00
private static String findMetaInfoFile(String iniFilePath) {
2024-04-01 13:44:53 -07:00
return FindFileHelper.findFile(iniFilePath, RUSEFI_INI_PREFIX, RUSEFI_INI_SUFFIX);
}
2016-01-17 22:01:46 -08:00
private void finishDialog() {
if (fieldsOfCurrentDialog.isEmpty())
2016-01-17 22:01:46 -08:00
return;
2016-03-21 14:02:08 -07:00
if (dialogUiName == null)
2017-02-05 15:04:56 -08:00
dialogUiName = dialogId;
dialogs.put(dialogUiName, new DialogModel(dialogId, dialogUiName, fieldsOfCurrentDialog));
2016-01-17 22:01:46 -08:00
2016-01-19 20:02:48 -08:00
dialogId = null;
fieldsOfCurrentDialog.clear();
2016-01-17 22:01:46 -08:00
}
2017-03-01 14:13:48 -08:00
private void handleLine(RawIniFile.Line line) {
2020-04-29 19:34:51 -07:00
2020-07-02 18:20:52 -07:00
String rawText = line.getRawText();
2016-01-15 20:01:43 -08:00
try {
2017-03-01 14:13:48 -08:00
LinkedList<String> list = new LinkedList<>(Arrays.asList(line.getTokens()));
2023-11-25 15:49:17 -08:00
if (!list.isEmpty() && list.get(0).equals("#define")) {
2023-11-25 18:13:18 -08:00
defines.put(list.get(1), list.subList(2, list.size()));
2023-11-25 15:49:17 -08:00
return;
}
2015-12-23 19:01:26 -08:00
2020-05-16 19:51:47 -07:00
if (!list.isEmpty() && list.get(0).equals(SECTION_PAGE)) {
isInsidePageDefinition = true;
return;
}
2020-04-29 19:34:51 -07:00
// todo: use TSProjectConsumer constant
if (isInSettingContextHelp) {
// todo: use TSProjectConsumer constant
2020-07-02 18:20:52 -07:00
if (rawText.contains("SettingContextHelpEnd")) {
2020-04-29 19:34:51 -07:00
isInSettingContextHelp = false;
}
if (list.size() == 2)
tooltips.put(list.get(0), list.get(1));
return;
2020-07-02 18:20:52 -07:00
} else if (rawText.contains("SettingContextHelp")) {
2020-05-16 19:51:47 -07:00
isInsidePageDefinition = false;
2020-04-29 19:34:51 -07:00
isInSettingContextHelp = true;
return;
}
2020-07-02 18:20:52 -07:00
if (RawIniFile.Line.isCommentLine(rawText))
2020-04-29 19:34:51 -07:00
return;
if (RawIniFile.Line.isPreprocessorDirective(rawText))
return;
2016-01-15 20:01:43 -08:00
trim(list);
2015-12-23 19:01:26 -08:00
2016-01-15 20:01:43 -08:00
if (list.isEmpty())
return;
2015-12-23 19:01:26 -08:00
String first = list.getFirst();
if (first.startsWith("[") && first.endsWith("]")) {
log.info("Section " + first);
isConstantsSection = first.equals("[Constants]");
}
2020-10-03 15:58:59 -07:00
if (isConstantsSection) {
if (isInsidePageDefinition) {
if (list.size() > 1)
handleFieldDefinition(list, line);
2020-10-03 15:58:59 -07:00
return;
} else {
if (list.size() > 1) {
protocolMeta.put(list.get(0), list.get(1));
}
}
2020-05-16 19:51:47 -07:00
}
2020-04-29 19:34:51 -07:00
2023-06-16 13:40:45 -07:00
switch (first) {
case "field":
handleField(list);
break;
2024-04-23 19:35:50 -07:00
case "slider":
handleSlider(list);
break;
2023-06-16 13:40:45 -07:00
case "dialog":
handleDialog(list);
break;
case "table":
handleTable(list);
break;
case "xBins":
handleXBins(list);
break;
case "yBins":
handleYBins(list);
break;
case "zBins":
handleZBins(list);
break;
2015-12-23 19:01:26 -08:00
}
2016-01-15 20:01:43 -08:00
} catch (RuntimeException e) {
2023-06-29 16:19:42 -07:00
throw new IllegalStateException("Failed to handle [" + rawText + "]: " + e, e);
2015-12-23 19:01:26 -08:00
}
}
private void handleZBins(LinkedList<String> list) {
list.removeFirst();
String zBins = list.removeFirst();
addField(zBins);
if (currentXBins == null || currentYBins == null)
throw new IllegalStateException("X or Y missing for " + zBins);
xBinsByZBins.put(zBins, currentXBins);
yBinsByZBins.put(zBins, currentYBins);
}
public String getXBin(String tableName) {
return xBinsByZBins.get(tableName);
}
public Set<String> getTables() {
return xBinsByZBins.keySet();
}
public String getYBin(String tableName) {
return yBinsByZBins.get(tableName);
}
private void handleYBins(LinkedList<String> list) {
list.removeFirst();
currentYBins = list.removeFirst();
addField(currentYBins);
}
private void handleXBins(LinkedList<String> list) {
list.removeFirst();
currentXBins = list.removeFirst();
addField(currentXBins);
}
private void addField(String key) {
DialogModel.Field field = new DialogModel.Field(key, key);
fieldsInUiOrder.put(key, field);
}
private void handleTable(LinkedList<String> list) {
list.removeFirst();
String tableName = list.removeFirst();
}
private void handleFieldDefinition(LinkedList<String> list, RawIniFile.Line line) {
2023-06-16 13:40:45 -07:00
switch (list.get(1)) {
case FIELD_TYPE_SCALAR:
registerField(ScalarIniField.parse(list));
break;
case FIELD_TYPE_STRING:
registerField(StringIniField.parse(list));
break;
case FIELD_TYPE_ARRAY:
registerField(ArrayIniField.parse(list));
break;
case FIELD_TYPE_BITS:
2023-11-25 15:49:17 -08:00
registerField(EnumIniField.parse(list, line, this));
2023-06-16 13:40:45 -07:00
break;
default:
throw new IllegalStateException("Unexpected " + list);
2020-05-16 19:51:47 -07:00
}
}
2020-05-16 20:49:20 -07:00
private void registerField(IniField field) {
if (allIniFields.containsKey(field.getName()))
return;
2020-05-16 20:49:20 -07:00
allIniFields.put(field.getName(), field);
}
2024-04-23 19:35:50 -07:00
private void handleSlider(LinkedList<String> list) {
list.removeFirst(); // "slider"
String uiFieldName = list.isEmpty() ? "" : list.removeFirst();
String key = list.isEmpty() ? null : list.removeFirst();
registerUiField(key, uiFieldName);
log.debug("IniFileModel: Slider label=[" + uiFieldName + "] : key=[" + key + "]");
}
private void handleField(LinkedList<String> list) {
list.removeFirst(); // "field"
String uiFieldName = list.isEmpty() ? "" : list.removeFirst();
String key = list.isEmpty() ? null : list.removeFirst();
registerUiField(key, uiFieldName);
log.debug("IniFileModel: Field label=[" + uiFieldName + "] : key=[" + key + "]");
}
private void registerUiField(String key, String uiFieldName) {
DialogModel.Field field = new DialogModel.Field(key, uiFieldName);
if (key != null) {
fieldsOfCurrentDialog.add(field);
fieldsInUiOrder.put(key, field);
}
}
2016-01-15 20:01:43 -08:00
private void handleDialog(LinkedList<String> list) {
2016-01-17 22:01:46 -08:00
finishDialog();
2016-01-15 20:01:43 -08:00
list.removeFirst(); // "dialog"
2020-05-16 19:51:47 -07:00
// trim(list);
2016-01-15 20:01:43 -08:00
String keyword = list.removeFirst();
// trim(list);
String name = list.isEmpty() ? null : list.removeFirst();
2016-01-19 20:02:48 -08:00
dialogId = keyword;
dialogUiName = name;
2020-07-29 16:25:25 -07:00
log.debug("IniFileModel: Dialog key=" + keyword + ": name=[" + name + "]");
2016-01-15 20:01:43 -08:00
}
2015-12-23 19:01:26 -08:00
private void trim(LinkedList<String> list) {
while (!list.isEmpty() && list.getFirst().isEmpty())
list.removeFirst();
}
2020-06-13 18:51:09 -07:00
public IniField findByOffset(int i) {
for (IniField field : allIniFields.values()) {
if (i >= field.getOffset() && i < field.getOffset() + field.getSize())
return field;
}
return null;
}
2020-05-19 23:51:14 -07:00
public static synchronized IniFileModel getInstance() {
if (INSTANCE == null) {
INSTANCE = new IniFileModel();
2020-06-12 22:07:48 -07:00
INSTANCE.findAndReadIniFile(INI_FILE_PATH);
}
2016-01-19 20:02:48 -08:00
return INSTANCE;
}
public Map<String, DialogModel> getDialogs() {
return dialogs;
}
2015-12-23 19:01:26 -08:00
}