franta-hg@31: /** franta-hg@31: * Rozšířené atributy – program na správu rozšířených atributů souborů franta-hg@31: * Copyright © 2023 František Kučera (frantovo.cz) franta-hg@31: * franta-hg@31: * This program is free software: you can redistribute it and/or modify franta-hg@31: * it under the terms of the GNU General Public License as published by franta-hg@31: * the Free Software Foundation, either version 3 of the License. franta-hg@31: * franta-hg@31: * This program is distributed in the hope that it will be useful, franta-hg@31: * but WITHOUT ANY WARRANTY; without even the implied warranty of franta-hg@31: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the franta-hg@31: * GNU General Public License for more details. franta-hg@31: * franta-hg@31: * You should have received a copy of the GNU General Public License franta-hg@31: * along with this program. If not, see . franta-hg@31: */ franta-hg@31: package cz.frantovo.rozsireneatributy; franta-hg@31: franta-hg@31: import cz.frantovo.rozsireneatributy.Konfigurace.DefiniceAtributu; franta-hg@31: import cz.frantovo.rozsireneatributy.Konfigurace.DefiniceHodnoty; franta-hg@31: import java.io.File; franta-hg@31: import java.util.Arrays; franta-hg@31: import java.util.Collection; franta-hg@31: import java.util.ResourceBundle; franta-hg@31: franta-hg@31: /** franta-hg@31: * Converts command line arguments from String array to object. Checks basic franta-hg@31: * constraints (if only supported options are used and if they have correct franta-hg@31: * number of parameters) franta-hg@31: * franta-hg@31: * @author Ing. František Kučera (frantovo.cz) franta-hg@31: */ franta-hg@31: public class CLIParser { franta-hg@31: franta-hg@31: private static final ResourceBundle překlady = ResourceBundle franta-hg@31: .getBundle(Atribut.class.getPackageName() + ".Překlady"); franta-hg@31: franta-hg@31: public Konfigurace parsujParametry(String[] parametry) franta-hg@31: throws CLIParserException { franta-hg@31: Konfigurace k = new Konfigurace(); franta-hg@31: franta-hg@31: for (int i = 0; i < parametry.length; i++) { franta-hg@31: String parametr = parametry[i]; franta-hg@31: franta-hg@31: boolean odpovídá = false; franta-hg@31: franta-hg@31: for (Token t : Token.values()) { franta-hg@31: if (t.odpovídá(parametr)) { franta-hg@31: int parsedArgs = t.parsuj(parametry, i, k); franta-hg@31: i = i + parsedArgs; franta-hg@31: odpovídá = true; franta-hg@31: } franta-hg@31: } franta-hg@31: franta-hg@31: if (!odpovídá) { franta-hg@31: throw new CLIParserException( franta-hg@31: překlady.getString("chyba.cli.neznámýParametr") + parametr); franta-hg@31: } franta-hg@31: } franta-hg@31: franta-hg@31: if (k.getSoubor() == null) franta-hg@31: throw new CLIParserException( franta-hg@31: překlady.getString("chyba.cli.chybíSoubor")); franta-hg@31: franta-hg@31: return k; franta-hg@31: } franta-hg@31: franta-hg@31: private static String načtiDalší(String[] parametry, int index) franta-hg@31: throws CLIParserException { franta-hg@31: if (index < parametry.length) { franta-hg@31: return parametry[index]; franta-hg@31: } else { franta-hg@31: throw new CLIParserException("Expecting value for option: " franta-hg@31: + parametry[index - 1]); franta-hg@31: } franta-hg@31: } franta-hg@31: franta-hg@31: private static boolean načtiDalšíBoolean(String[] parametry, int index) franta-hg@31: throws CLIParserException { franta-hg@31: String s = načtiDalší(parametry, index); franta-hg@31: switch (s) { franta-hg@31: case "true": franta-hg@31: case "ano": franta-hg@31: return true; franta-hg@31: case "false": franta-hg@31: case "ne": franta-hg@31: return false; franta-hg@31: default: franta-hg@31: throw new CLIParserException("Neplatná logická hodnota: " + s); franta-hg@31: } franta-hg@31: } franta-hg@31: franta-hg@31: private static enum Token { franta-hg@31: franta-hg@31: SOUBOR("--soubor", "--file") { franta-hg@31: @Override franta-hg@31: public int parsuj(String[] parametry, int index, Konfigurace k) franta-hg@31: throws CLIParserException { franta-hg@31: int originalIndex = index; franta-hg@31: k.setSoubor(new File(načtiDalší(parametry, ++index))); franta-hg@31: return index - originalIndex; franta-hg@31: } franta-hg@31: }, franta-hg@31: POVINNÉ_ZAMYKÁNÍ("--povinné-zamykání", "--mandatory-locking") { franta-hg@31: @Override franta-hg@31: public int parsuj(String[] parametry, int index, Konfigurace k) franta-hg@31: throws CLIParserException { franta-hg@31: int originalIndex = index; franta-hg@31: k.setPovinnéZamykání(načtiDalšíBoolean(parametry, ++index)); franta-hg@31: return index - originalIndex; franta-hg@31: } franta-hg@31: }, franta-hg@31: DEFINICE_ATRIBUTU("--definice-atributu", "--attribute-definition") { franta-hg@31: @Override franta-hg@31: public int parsuj(String[] parametry, int index, Konfigurace k) franta-hg@31: throws CLIParserException { franta-hg@31: int originalIndex = index; franta-hg@31: String název = načtiDalší(parametry, ++index); franta-hg@31: String popis = načtiDalší(parametry, ++index); franta-hg@31: k.addAtribut(new DefiniceAtributu(název, popis)); franta-hg@31: return index - originalIndex; franta-hg@31: } franta-hg@31: }, franta-hg@31: HODNOTA_ATRIBUTU("--hodnota", "--value") { franta-hg@31: @Override franta-hg@31: public int parsuj(String[] parametry, int index, Konfigurace k) franta-hg@31: throws CLIParserException { franta-hg@31: int originalIndex = index; franta-hg@31: String hodnota = načtiDalší(parametry, ++index); franta-hg@31: String popis = načtiDalší(parametry, ++index); franta-hg@31: franta-hg@31: if (k.getAtributy().isEmpty()) franta-hg@31: throw new CLIParserException( franta-hg@31: překlady.getString("chyba.cli.chybíDefiniceAtributu")); franta-hg@31: franta-hg@31: k.getAtributy() franta-hg@31: .get(k.getAtributy().size() - 1) franta-hg@31: .addHodnota(new DefiniceHodnoty(hodnota, popis)); franta-hg@31: franta-hg@31: return index - originalIndex; franta-hg@31: } franta-hg@31: }; franta-hg@31: franta-hg@31: private final Collection parametry; franta-hg@31: franta-hg@31: private Token(String... parametry) { franta-hg@31: this.parametry = Arrays.asList(parametry); franta-hg@31: } franta-hg@31: franta-hg@31: /** franta-hg@31: * @param parametr e.g. „--input-file“ franta-hg@31: * @return whether option is this token franta-hg@31: */ franta-hg@31: public boolean odpovídá(String parametr) { franta-hg@31: return parametry.contains(parametr); franta-hg@31: } franta-hg@31: franta-hg@31: /** franta-hg@31: * Parse String arguments and fill values into the options object. franta-hg@31: * franta-hg@31: * @param parametry CLI arguments franta-hg@31: * @param index index of the option matched by this token, like franta-hg@31: * „--input-file“ franta-hg@31: * @param k object to be filled franta-hg@31: * @return number of parsed arguments – if option has no arguments (just franta-hg@31: * boolean flag), return 0, otherwise return positive integer: number of franta-hg@31: * eaten arguments. franta-hg@31: * @throws CLIParserException franta-hg@31: */ franta-hg@31: public abstract int parsuj(String[] parametry, int index, Konfigurace k) franta-hg@31: throws CLIParserException; franta-hg@31: } franta-hg@31: }