Skip to content

Commit 42911e5

Browse files
authored
Merge pull request #71 from arnaud-m/feature-70
Define verbosity levels with an enumeration. - Not backward compatible with the boolean option verbose. - close #70
2 parents 72a1b8f + 78ab826 commit 42911e5

16 files changed

+237
-107
lines changed

src/main/java/cryptator/Cryptagen.java

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,12 @@
1616
import java.util.logging.Level;
1717
import java.util.logging.Logger;
1818

19-
import cryptator.cmd.AbstractOptionsParser;
2019
import cryptator.cmd.CryptaBiConsumer;
20+
import cryptator.cmd.OptionsParserWithLog;
2121
import cryptator.cmd.WordArray;
2222
import cryptator.config.CryptagenConfig;
2323
import cryptator.gen.CryptaListGenerator;
2424
import cryptator.solver.CryptaModelException;
25-
import cryptator.solver.CryptaSolver;
2625

2726
public final class Cryptagen {
2827

@@ -44,6 +43,8 @@ public static int doMain(final String[] args) {
4443
final WordArray words = buildWords(config.getArguments(), config);
4544
if (words != null) {
4645
return generate(words, config);
46+
} else {
47+
LOGGER.log(Level.WARNING, "Empty word list.");
4748
}
4849
}
4950
JULogUtil.flushLogs();
@@ -96,25 +97,14 @@ private static WordArray buildWords(final List<String> arguments, final Cryptage
9697
}
9798
}
9899

99-
private static final class CryptagenOptionsParser extends AbstractOptionsParser<CryptagenConfig> {
100+
private static final class CryptagenOptionsParser extends OptionsParserWithLog<CryptagenConfig> {
100101

101-
protected CryptagenOptionsParser() {
102-
super(Cryptagen.class, new CryptagenConfig());
103-
}
102+
private static final String ARG_NAME = "WORDS...";
104103

105-
@Override
106-
protected void configureLoggers() {
107-
if (config.isVerbose()) {
108-
JULogUtil.configureLoggers(Level.ALL);
109-
} else {
110-
JULogUtil.setLevel(Level.WARNING, CryptaSolver.LOGGER);
111-
}
104+
protected CryptagenOptionsParser() {
105+
super(Cryptagen.class, new CryptagenConfig(), ARG_NAME, JULogUtil.getDefaultLogManager());
112106
}
113107

114-
@Override
115-
public String getArgumentName() {
116-
return "WORDS...";
117-
}
118108
}
119109

120110
private static CryptaBiConsumer buildBiConsumer(final CryptagenConfig config) {
@@ -127,6 +117,7 @@ private static CryptaBiConsumer buildBiConsumer(final CryptagenConfig config) {
127117
}
128118

129119
private static int generate(final WordArray words, final CryptagenConfig config) {
120+
LOGGER.log(Level.CONFIG, () -> "Word List Features:\n" + words.toDimacs());
130121
final CryptaListGenerator gen = new CryptaListGenerator(words, config, LOGGER);
131122
final CryptaBiConsumer cons = buildBiConsumer(config);
132123
try {

src/main/java/cryptator/Cryptamancer.java

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
import java.util.logging.Level;
1313
import java.util.logging.Logger;
1414

15-
import cryptator.cmd.AbstractOptionsParser;
15+
import cryptator.cmd.OptionsParserWithLog;
1616
import cryptator.config.CryptaConfig;
17-
import cryptator.config.CryptamancerConfig;
17+
import cryptator.config.CryptaLogConfig;
1818
import cryptator.game.CryptaGameDecision;
1919
import cryptator.game.CryptaGameEngine;
2020
import cryptator.game.CryptaGameException;
@@ -29,22 +29,12 @@ public final class Cryptamancer {
2929

3030
public static final Logger LOGGER = Logger.getLogger(Cryptamancer.class.getName());
3131

32-
private static class CryptamancerOptionsParser extends AbstractOptionsParser<CryptamancerConfig> {
32+
private static class CryptamancerOptionsParser extends OptionsParserWithLog<CryptaLogConfig> {
3333

34-
protected CryptamancerOptionsParser() {
35-
super(Cryptamancer.class, new CryptamancerConfig());
36-
}
37-
38-
@Override
39-
protected void configureLoggers() {
40-
if (config.isVerbose()) {
41-
JULogUtil.setLevel(Level.CONFIG, getLogger(), CryptaGameEngine.LOGGER);
42-
}
43-
}
34+
private static final String ARG_NAME = "CRYPTARITHM";
4435

45-
@Override
46-
public String getArgumentName() {
47-
return "CRYPTARITHM";
36+
protected CryptamancerOptionsParser() {
37+
super(Cryptamancer.class, new CryptaLogConfig(), ARG_NAME, JULogUtil.getDefaultLogManager());
4838
}
4939

5040
@Override
@@ -57,7 +47,7 @@ private Cryptamancer() {
5747
super();
5848
}
5949

60-
public static ICryptaNode parseCryptarithm(final CryptamancerConfig config) {
50+
public static ICryptaNode parseCryptarithm(final CryptaLogConfig config) {
6151
final String cryptarithm = config.getArguments().get(0);
6252
try {
6353
return Cryptator.parseCryptarithm(cryptarithm, new CryptaParserWrapper(), LOGGER);
@@ -111,7 +101,7 @@ public static void main(final String[] args) throws Exception {
111101
if (!optparser.parseOptions(args)) {
112102
return;
113103
}
114-
final CryptamancerConfig config = optparser.getConfig();
104+
final CryptaLogConfig config = optparser.getConfig();
115105

116106
final ICryptaNode node = parseCryptarithm(config);
117107
if (node == null) {

src/main/java/cryptator/Cryptator.java

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
import java.util.logging.Level;
1212
import java.util.logging.Logger;
1313

14-
import cryptator.cmd.AbstractOptionsParser;
1514
import cryptator.cmd.CryptaBiConsumer;
15+
import cryptator.cmd.OptionsParserWithLog;
1616
import cryptator.config.CryptatorConfig;
1717
import cryptator.parser.CryptaParserException;
1818
import cryptator.parser.CryptaParserWrapper;
@@ -54,22 +54,12 @@ public static int doMain(final String[] args) {
5454
return exitCode;
5555
}
5656

57-
private static class CryptatorOptionsParser extends AbstractOptionsParser<CryptatorConfig> {
57+
private static class CryptatorOptionsParser extends OptionsParserWithLog<CryptatorConfig> {
5858

59-
CryptatorOptionsParser() {
60-
super(Cryptator.class, new CryptatorConfig());
61-
}
62-
63-
@Override
64-
public String getArgumentName() {
65-
return "CRYPTARITHMS...";
66-
}
59+
private static final String ARG_NAME = "CRYPTARITHMS...";
6760

68-
@Override
69-
protected void configureLoggers() {
70-
if (config.isVerbose()) {
71-
JULogUtil.configureLoggers(Level.ALL);
72-
}
61+
CryptatorOptionsParser() {
62+
super(Cryptator.class, new CryptatorConfig(), ARG_NAME, JULogUtil.getDefaultLogManager());
7363
}
7464
}
7565

src/main/java/cryptator/JULogUtil.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import cryptator.game.CryptaGameEngine;
2020
import cryptator.solver.CryptaSolver;
21+
import cryptator.specs.ICryptaLogManager;
2122

2223
public final class JULogUtil {
2324

@@ -62,7 +63,7 @@ public static void setLevel(final Level level, final Logger... loggers) {
6263
}
6364

6465
public static void flushLogs(final Logger logger) {
65-
logger.log(Level.FINE, "Flush logger {0}", logger.getName());
66+
logger.log(Level.FINEST, "Flush logger {0}", logger.getName());
6667
for (Handler handler : logger.getHandlers()) {
6768
handler.flush();
6869
}
@@ -78,6 +79,33 @@ public static void flushLogs() {
7879
flushLogs(manager.getLogger(name));
7980
}
8081
}
82+
}
83+
84+
public static final ICryptaLogManager DEFAULT_LOG_MANAGER = new DefaultLogManager();
85+
86+
public static ICryptaLogManager getDefaultLogManager() {
87+
return DEFAULT_LOG_MANAGER;
88+
}
89+
90+
private static class DefaultLogManager implements ICryptaLogManager {
91+
92+
@Override
93+
public void setQuiet() {
94+
ICryptaLogManager.super.setQuiet();
95+
JULogUtil.setLevel(Level.INFO, Cryptagen.LOGGER, Cryptator.LOGGER);
96+
}
97+
98+
@Override
99+
public void setNormal() {
100+
ICryptaLogManager.super.setNormal();
101+
JULogUtil.setLevel(Level.CONFIG, Cryptagen.LOGGER);
102+
}
103+
104+
@Override
105+
public void setVerbose() {
106+
ICryptaLogManager.super.setVerbose();
107+
JULogUtil.setLevel(Level.FINE, Cryptagen.LOGGER);
108+
}
81109

82110
}
83111

src/main/java/cryptator/cmd/AbstractOptionsParser.java

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package cryptator.cmd;
1010

1111
import java.io.ByteArrayOutputStream;
12+
import java.io.OutputStreamWriter;
1213
import java.util.logging.Level;
1314
import java.util.logging.Logger;
1415

@@ -24,21 +25,26 @@ public abstract class AbstractOptionsParser<E extends CryptaConfig> {
2425

2526
protected final E config;
2627

27-
protected AbstractOptionsParser(final Class<?> mainClass, final E config) {
28+
private final String argumentName;
29+
30+
protected AbstractOptionsParser(final Class<?> mainClass, final E config, final String argumentName) {
2831
super();
2932
this.mainClass = mainClass;
3033
this.config = config;
34+
this.argumentName = argumentName;
3135
}
3236

3337
public final Logger getLogger() {
3438
return Logger.getLogger(mainClass.getName());
3539
}
3640

37-
protected final String getCommandName() {
41+
private final String getCommandName() {
3842
return mainClass.getName();
3943
}
4044

41-
protected abstract String getArgumentName();
45+
private final String getArgumentName() {
46+
return argumentName;
47+
}
4248

4349
protected abstract void configureLoggers();
4450

@@ -69,7 +75,8 @@ public final boolean parseOptions(final String[] args) {
6975
configureLoggers();
7076
if (checkConfiguration()) {
7177
if (checkArguments()) {
72-
getLogger().log(Level.CONFIG, "Parse options [OK]\n{0}", config);
78+
getLogger().log(Level.CONFIG, "Parse options [OK]");
79+
getLogger().log(Level.FINE, "Configuration:\n{0}", config);
7380
return true;
7481
} else {
7582
getLogger().log(Level.SEVERE, "Parse arguments [FAIL]\n{0}", config.getArguments());
@@ -83,25 +90,35 @@ public final boolean parseOptions(final String[] args) {
8390
}
8491

8592
if (getLogger().isLoggable(Level.INFO)) {
86-
getLogger().info(buildHelpMessage(parser));
93+
getLogger().info(buildHelpMessage(parser, OptionHandlerFilter.PUBLIC));
8794
}
8895
return false;
8996

9097
}
9198

92-
private String buildHelpMessage(CmdLineParser parser) {
93-
StringBuilder b = new StringBuilder();
94-
b.append(" Help:\n");
95-
b.append("java ").append(getCommandName()).append(" [options...] ").append(getArgumentName()).append("\n");
99+
private String printUsage(CmdLineParser parser, OptionHandlerFilter filter) {
96100
final ByteArrayOutputStream os = new ByteArrayOutputStream();
97-
parser.printUsage(os);
98-
b.append(os.toString());
99-
b.append("\nExamples:");
100-
b.append("\njava ").append(getCommandName()).append(" ")
101-
.append(parser.printExample(OptionHandlerFilter.REQUIRED)).append(" ").append(getArgumentName());
101+
parser.printUsage(new OutputStreamWriter(os), null, filter);
102+
return os.toString();
103+
}
104+
105+
private String printExample(String options) {
106+
return "java " + getCommandName() + " " + options + " " + getArgumentName();
107+
}
108+
109+
private String printExample(CmdLineParser parser, OptionHandlerFilter filter) {
110+
return printExample(parser.printExample(filter));
111+
}
102112

103-
b.append("\njava ").append(getCommandName()).append(" ").append(parser.printExample(OptionHandlerFilter.ALL))
104-
.append(" ").append(getArgumentName());
113+
private String buildHelpMessage(CmdLineParser parser, OptionHandlerFilter filter) {
114+
StringBuilder b = new StringBuilder();
115+
b.append(" Help message:\n");
116+
b.append(printExample("[options...]")).append("\n");
117+
b.append(printUsage(parser, filter));
118+
b.append("\nExamples:");
119+
b.append("\n").append(printExample(parser, OptionHandlerFilter.REQUIRED));
120+
b.append("\n").append(printExample(parser, filter));
105121
return b.toString();
106122
}
123+
107124
}

src/main/java/cryptator/cmd/CryptaBiConsumer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ private class SolutionChecker implements BiConsumer<ICryptaNode, ICryptaSolution
133133
public void accept(final ICryptaNode n, final ICryptaSolution s) {
134134
try {
135135
if (eval.evaluate(n, s, base).compareTo(BigInteger.ZERO) != 0) {
136-
logger.log(Level.CONFIG, "Eval cryptarithm solution #{0} [OK]", solutionCount);
136+
logger.log(Level.FINE, "Eval cryptarithm solution #{0} [OK]", solutionCount);
137137
} else {
138138
errorCount++;
139139
logger.log(Level.SEVERE, "Eval cryptarithm solution #{0} [KO]", solutionCount);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* This file is part of cryptator, https://github.com/arnaud-m/cryptator
3+
*
4+
* Copyright (c) 2022, Université Côte d'Azur. All rights reserved.
5+
*
6+
* Licensed under the BSD 3-clause license.
7+
* See LICENSE file in the project root for full license information.
8+
*/
9+
package cryptator.cmd;
10+
11+
import cryptator.config.CryptaLogConfig;
12+
import cryptator.specs.ICryptaLogManager;
13+
14+
public class OptionsParserWithLog<E extends CryptaLogConfig> extends AbstractOptionsParser<E> {
15+
16+
private final ICryptaLogManager logManager;
17+
18+
public OptionsParserWithLog(Class<?> mainClass, E config, String argumentName, ICryptaLogManager logManager) {
19+
super(mainClass, config, argumentName);
20+
this.logManager = logManager;
21+
}
22+
23+
@Override
24+
protected void configureLoggers() {
25+
config.getVerbosity().applyTo(logManager);
26+
}
27+
28+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* This file is part of cryptator, https://github.com/arnaud-m/cryptator
3+
*
4+
* Copyright (c) 2022, Université Côte d'Azur. All rights reserved.
5+
*
6+
* Licensed under the BSD 3-clause license.
7+
* See LICENSE file in the project root for full license information.
8+
*/
9+
package cryptator.cmd;
10+
11+
import cryptator.specs.ICryptaLogManager;
12+
13+
public enum Verbosity {
14+
SILENT, QUIET, NORMAL, VERBOSE, VERY_VERBOSE, DEBUG;
15+
16+
public void applyTo(ICryptaLogManager manager) {
17+
setVerbosity(manager, this);
18+
}
19+
20+
public static void setVerbosity(ICryptaLogManager manager, Verbosity verbosity) {
21+
if (verbosity != null && manager != null) {
22+
if (verbosity.equals(SILENT)) {
23+
manager.setSilent();
24+
} else if (verbosity.equals(QUIET)) {
25+
manager.setQuiet();
26+
} else if (verbosity.equals(NORMAL)) {
27+
manager.setNormal();
28+
} else if (verbosity.equals(VERBOSE)) {
29+
manager.setVerbose();
30+
} else if (verbosity.equals(VERY_VERBOSE)) {
31+
manager.setVeryVerbose();
32+
} else if (verbosity.equals(DEBUG)) {
33+
manager.setDebug();
34+
}
35+
}
36+
}
37+
}

src/main/java/cryptator/cmd/WordArray.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ public final int getUB() {
7070
return ub;
7171
}
7272

73+
public String toDimacs() {
74+
return "c WORDS " + words.length + "\nc RIGHT_MEMBER " + (hasRightMember() ? "FIXED" : "FREE")
75+
+ "\nc DOUBLY_TRUE " + (isDoublyTrue() ? lb + "-" + ub : "NO");
76+
}
77+
7378
@Override
7479
public String toString() {
7580
return "WordArray [words=" + Arrays.toString(words) + ", rightMember=" + rightMember + ", lb=" + lb + ", ub="

0 commit comments

Comments
 (0)