src/main/java/cz/frantovo/rozsireneatributy/CLIParser.java
author František Kučera <franta-hg@frantovo.cz>
Sun, 24 Dec 2023 00:38:41 +0100
branchv_0
changeset 42 d2414701ce09
parent 39 ec0e970e0830
permissions -rw-r--r--
režimy zamykání:

- vypnuté: tlačítko pro zamykání je skryté a soubor se nezamyká
- volitelné: uživatel může soubor zamknout, ale může editovat i bez toho
- povinné: uživatel musí soubor zamknout, aby mohl atributy editovat

Změny v atributech se vždy propisují okamžitě - na ně zámek nemá vliv.
Zámek je na souboru (ne metadatech) a slouží pro kooperující procesy.
Proces, který soubor/metadata čte, si jednak může soubor zamknout (POSIX)
a tím mít jistotu, že zrovna neprobíhá editace.
A jednak může reagovat na notifikace CLOSE_WRITE (inotify).
Notifikaci mu pošleme tím, že soubor odemkneme (čímž se i zavře).
franta-hg@31
     1
/**
franta-hg@31
     2
 * Rozšířené atributy – program na správu rozšířených atributů souborů
franta-hg@31
     3
 * Copyright © 2023 František Kučera (frantovo.cz)
franta-hg@31
     4
 *
franta-hg@31
     5
 * This program is free software: you can redistribute it and/or modify
franta-hg@31
     6
 * it under the terms of the GNU General Public License as published by
franta-hg@31
     7
 * the Free Software Foundation, either version 3 of the License.
franta-hg@31
     8
 *
franta-hg@31
     9
 * This program is distributed in the hope that it will be useful,
franta-hg@31
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
franta-hg@31
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
franta-hg@31
    12
 * GNU General Public License for more details.
franta-hg@31
    13
 *
franta-hg@31
    14
 * You should have received a copy of the GNU General Public License
franta-hg@31
    15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
franta-hg@31
    16
 */
franta-hg@31
    17
package cz.frantovo.rozsireneatributy;
franta-hg@31
    18
franta-hg@31
    19
import cz.frantovo.rozsireneatributy.Konfigurace.DefiniceAtributu;
franta-hg@31
    20
import cz.frantovo.rozsireneatributy.Konfigurace.DefiniceHodnoty;
franta-hg@42
    21
import cz.frantovo.rozsireneatributy.Konfigurace.RežimZamykání;
franta-hg@31
    22
import java.io.File;
franta-hg@31
    23
import java.util.Arrays;
franta-hg@31
    24
import java.util.Collection;
franta-hg@31
    25
import java.util.ResourceBundle;
franta-hg@31
    26
franta-hg@31
    27
/**
franta-hg@31
    28
 * Converts command line arguments from String array to object. Checks basic
franta-hg@31
    29
 * constraints (if only supported options are used and if they have correct
franta-hg@31
    30
 * number of parameters)
franta-hg@31
    31
 *
franta-hg@31
    32
 * @author Ing. František Kučera (frantovo.cz)
franta-hg@31
    33
 */
franta-hg@31
    34
public class CLIParser {
franta-hg@31
    35
franta-hg@31
    36
	private static final ResourceBundle překlady = ResourceBundle
franta-hg@31
    37
		.getBundle(Atribut.class.getPackageName() + ".Překlady");
franta-hg@31
    38
franta-hg@31
    39
	public Konfigurace parsujParametry(String[] parametry)
franta-hg@31
    40
		throws CLIParserException {
franta-hg@31
    41
		Konfigurace k = new Konfigurace();
franta-hg@31
    42
franta-hg@31
    43
		for (int i = 0; i < parametry.length; i++) {
franta-hg@31
    44
			String parametr = parametry[i];
franta-hg@31
    45
franta-hg@31
    46
			boolean odpovídá = false;
franta-hg@31
    47
franta-hg@31
    48
			for (Token t : Token.values()) {
franta-hg@31
    49
				if (t.odpovídá(parametr)) {
franta-hg@31
    50
					int parsedArgs = t.parsuj(parametry, i, k);
franta-hg@31
    51
					i = i + parsedArgs;
franta-hg@31
    52
					odpovídá = true;
franta-hg@31
    53
				}
franta-hg@31
    54
			}
franta-hg@31
    55
franta-hg@31
    56
			if (!odpovídá) {
franta-hg@31
    57
				throw new CLIParserException(
franta-hg@31
    58
					překlady.getString("chyba.cli.neznámýParametr") + parametr);
franta-hg@31
    59
			}
franta-hg@31
    60
		}
franta-hg@31
    61
franta-hg@31
    62
		if (k.getSoubor() == null)
franta-hg@31
    63
			throw new CLIParserException(
franta-hg@42
    64
				překlady.getString("chyba.cli.chybíSoubor"));
franta-hg@42
    65
franta-hg@31
    66
		return k;
franta-hg@31
    67
	}
franta-hg@31
    68
franta-hg@31
    69
	private static String načtiDalší(String[] parametry, int index)
franta-hg@31
    70
		throws CLIParserException {
franta-hg@31
    71
		if (index < parametry.length) {
franta-hg@31
    72
			return parametry[index];
franta-hg@31
    73
		} else {
franta-hg@31
    74
			throw new CLIParserException("Expecting value for option: "
franta-hg@31
    75
				+ parametry[index - 1]);
franta-hg@31
    76
		}
franta-hg@31
    77
	}
franta-hg@31
    78
franta-hg@31
    79
	private static boolean načtiDalšíBoolean(String[] parametry, int index)
franta-hg@31
    80
		throws CLIParserException {
franta-hg@31
    81
		String s = načtiDalší(parametry, index);
franta-hg@31
    82
		switch (s) {
franta-hg@31
    83
			case "true":
franta-hg@31
    84
			case "ano":
franta-hg@31
    85
				return true;
franta-hg@31
    86
			case "false":
franta-hg@31
    87
			case "ne":
franta-hg@31
    88
				return false;
franta-hg@31
    89
			default:
franta-hg@31
    90
				throw new CLIParserException("Neplatná logická hodnota: " + s);
franta-hg@31
    91
		}
franta-hg@31
    92
	}
franta-hg@31
    93
franta-hg@31
    94
	private static enum Token {
franta-hg@31
    95
franta-hg@31
    96
		SOUBOR("--soubor", "--file") {
franta-hg@31
    97
			@Override
franta-hg@31
    98
			public int parsuj(String[] parametry, int index, Konfigurace k)
franta-hg@31
    99
				throws CLIParserException {
franta-hg@31
   100
				int originalIndex = index;
franta-hg@31
   101
				k.setSoubor(new File(načtiDalší(parametry, ++index)));
franta-hg@31
   102
				return index - originalIndex;
franta-hg@31
   103
			}
franta-hg@31
   104
		},
franta-hg@42
   105
		REŽIM_ZAMYKÁNÍ("--režim-zamykání", "--locking-mode") {
franta-hg@31
   106
			@Override
franta-hg@31
   107
			public int parsuj(String[] parametry, int index, Konfigurace k)
franta-hg@31
   108
				throws CLIParserException {
franta-hg@31
   109
				int originalIndex = index;
franta-hg@42
   110
				String hodnota = načtiDalší(parametry, ++index);
franta-hg@42
   111
				k.setRežimZamykání(RežimZamykání.najdiRežim(hodnota));
franta-hg@42
   112
				if (k.getRežimZamykání() == null)
franta-hg@42
   113
					throw new CLIParserException(
franta-hg@42
   114
						// TODO: překlad:
franta-hg@42
   115
						"Neplatný režim zamykání: " + hodnota);
franta-hg@31
   116
				return index - originalIndex;
franta-hg@31
   117
			}
franta-hg@31
   118
		},
franta-hg@31
   119
		DEFINICE_ATRIBUTU("--definice-atributu", "--attribute-definition") {
franta-hg@31
   120
			@Override
franta-hg@31
   121
			public int parsuj(String[] parametry, int index, Konfigurace k)
franta-hg@31
   122
				throws CLIParserException {
franta-hg@31
   123
				int originalIndex = index;
franta-hg@31
   124
				String název = načtiDalší(parametry, ++index);
franta-hg@31
   125
				String popis = načtiDalší(parametry, ++index);
franta-hg@31
   126
				k.addAtribut(new DefiniceAtributu(název, popis));
franta-hg@31
   127
				return index - originalIndex;
franta-hg@31
   128
			}
franta-hg@31
   129
		},
franta-hg@31
   130
		HODNOTA_ATRIBUTU("--hodnota", "--value") {
franta-hg@31
   131
			@Override
franta-hg@31
   132
			public int parsuj(String[] parametry, int index, Konfigurace k)
franta-hg@31
   133
				throws CLIParserException {
franta-hg@31
   134
				int originalIndex = index;
franta-hg@31
   135
				String hodnota = načtiDalší(parametry, ++index);
franta-hg@31
   136
				String popis = načtiDalší(parametry, ++index);
franta-hg@31
   137
franta-hg@31
   138
				if (k.getAtributy().isEmpty())
franta-hg@31
   139
					throw new CLIParserException(
franta-hg@31
   140
						překlady.getString("chyba.cli.chybíDefiniceAtributu"));
franta-hg@31
   141
franta-hg@31
   142
				k.getAtributy()
franta-hg@31
   143
					.get(k.getAtributy().size() - 1)
franta-hg@31
   144
					.addHodnota(new DefiniceHodnoty(hodnota, popis));
franta-hg@31
   145
franta-hg@31
   146
				return index - originalIndex;
franta-hg@31
   147
			}
franta-hg@31
   148
		};
franta-hg@31
   149
franta-hg@31
   150
		private final Collection<String> parametry;
franta-hg@31
   151
franta-hg@31
   152
		private Token(String... parametry) {
franta-hg@31
   153
			this.parametry = Arrays.asList(parametry);
franta-hg@31
   154
		}
franta-hg@31
   155
franta-hg@31
   156
		/**
franta-hg@31
   157
		 * @param parametr e.g. „--input-file“
franta-hg@31
   158
		 * @return whether option is this token
franta-hg@31
   159
		 */
franta-hg@31
   160
		public boolean odpovídá(String parametr) {
franta-hg@31
   161
			return parametry.contains(parametr);
franta-hg@31
   162
		}
franta-hg@31
   163
franta-hg@31
   164
		/**
franta-hg@31
   165
		 * Parse String arguments and fill values into the options object.
franta-hg@31
   166
		 *
franta-hg@31
   167
		 * @param parametry CLI arguments
franta-hg@31
   168
		 * @param index index of the option matched by this token, like
franta-hg@31
   169
		 * „--input-file“
franta-hg@31
   170
		 * @param k object to be filled
franta-hg@31
   171
		 * @return number of parsed arguments – if option has no arguments (just
franta-hg@31
   172
		 * boolean flag), return 0, otherwise return positive integer: number of
franta-hg@31
   173
		 * eaten arguments.
franta-hg@31
   174
		 * @throws CLIParserException
franta-hg@31
   175
		 */
franta-hg@31
   176
		public abstract int parsuj(String[] parametry, int index, Konfigurace k)
franta-hg@31
   177
			throws CLIParserException;
franta-hg@31
   178
	}
franta-hg@31
   179
}