1   package eu.fbk.dh.tint.runner;
2   
3   import com.google.common.base.Throwables;
4   import eu.fbk.utils.core.CommandLine;
5   import org.slf4j.Logger;
6   import org.slf4j.LoggerFactory;
7   
8   import java.io.*;
9   import java.lang.reflect.InvocationTargetException;
10  import java.lang.reflect.Method;
11  import java.lang.reflect.Modifier;
12  import java.util.List;
13  import java.util.Properties;
14  
15  /**
16   * Created by alessio on 03/08/16.
17   */
18  
19  public class TintRunner {
20  
21      private static final Logger LOGGER = LoggerFactory.getLogger(TintRunner.class);
22  
23      public static enum OutputFormat {
24          READABLE, JSON, XML, CONLL, NAF, TEXTPRO
25      }
26  
27      public static void main(String[] args) {
28          try {
29              final CommandLine cmd = CommandLine
30                      .parser()
31                      .withName("tint")
32                      .withHeader("Run the Tint pipeline.")
33                      .withOption("c", "config-file", "Configuration file", "FILE",
34                              CommandLine.Type.FILE_EXISTING, true, false, false)
35                      .withOption("i", "input-file", "Input text file (default stdin)", "FILE",
36                              CommandLine.Type.FILE_EXISTING, true, false, false)
37                      .withOption("o", "output-file", "Output processed file (default stdout)", "FILE",
38                              CommandLine.Type.FILE_EXISTING, true, false, false)
39                      .withOption("f", "output-format",
40                              "Output format: textpro, json, xml, conll, readable (default conll)",
41                              "FORMAT",
42                              CommandLine.Type.STRING, true, false, false)
43                      .withOption(null, "properties", "Additional properties for Stanford CoreNLP", "PROPS",
44                              CommandLine.Type.STRING, true, false, false)
45                      .withLogger(LoggerFactory.getLogger("eu.fbk")).parse(args);
46  
47              final File inputPath = cmd.getOptionValue("i", File.class);
48              final File outputPath = cmd.getOptionValue("o", File.class);
49              final File configPath = cmd.getOptionValue("c", File.class);
50  
51              List<String> addProperties = cmd.getOptionValues("properties", String.class);
52              Properties additionalProps = new Properties();
53              for (String property : addProperties) {
54                  try {
55                      additionalProps.load(new StringReader(property));
56                  } catch (Exception e) {
57                      // continue
58                  }
59              }
60  
61              Console console = System.console();
62              if (console == null) {
63                  final String loggerClassName = LOGGER.getClass().getName();
64                  if (loggerClassName.equals("ch.qos.logback.classic.Logger")) {
65                      final Class<?> levelClass = Class.forName("ch.qos.logback.classic.Level");
66                      final Object level = call(levelClass, "valueOf", "OFF");
67                      call(LOGGER, "setLevel", level);
68                  } else if (loggerClassName.equals("org.apache.log4j.Logger")) {
69                      final Class<?> levelClass = Class.forName("org.apache.log4j.Level");
70                      final Object level = call(levelClass, "valueOf", "OFF");
71                      call(LOGGER, "setLevel", level);
72                  } else if (loggerClassName.equals("org.apache.logging.slf4j.Log4jLogger")) {
73  
74                      // todo: check
75                      final Class<?> managerClass = Class
76                              .forName("org.apache.logging.log4j.LogManager");
77                      final Object ctx = call(managerClass, "getContext", false);
78                      final Object config = call(ctx, "getConfiguration");
79                      final Object logConfig = call(config, "getLoggerConfig",
80                              LOGGER.getName());
81                      final Class<?> levelClass = Class
82                              .forName("org.apache.logging.log4j.Level");
83                      final Object level = call(levelClass, "valueOf", "OFF");
84                      call(logConfig, "setLevel", level);
85                      call(ctx, "updateLoggers");
86                  }
87  
88  //            if (outputPath == null) {
89                  // todo: disable logging at all
90  //                ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)).setLevel(Level.OFF);
91  //                ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger("eu.fbk")).setLevel(Level.OFF);
92              }
93  
94              final String formatString = cmd.getOptionValue("f", String.class);
95              OutputFormat format = getOutputFormat(formatString, OutputFormat.JSON);
96  
97              // Input
98  
99              InputStream inputStream;
100 //            Reader reader;
101 
102             if (inputPath != null) {
103                 inputStream = new FileInputStream(inputPath);
104             } else {
105                 inputStream = System.in;
106             }
107 
108             // Text annotation
109 
110             TintPipeline pipeline = new TintPipeline();
111             pipeline.loadDefaultProperties();
112             pipeline.loadPropertiesFromFile(configPath);
113             pipeline.addProperties(additionalProps);
114             pipeline.load();
115             System.err.println("Tint is ready");
116 
117             // Output
118 
119             OutputStream outputStream = System.out;
120             if (outputPath != null) {
121                 outputStream = new FileOutputStream(outputPath);
122             }
123 
124             pipeline.run(inputStream, outputStream, format);
125 
126         } catch (Exception e) {
127             CommandLine.fail(e);
128         }
129     }
130 
131     public static OutputFormat getOutputFormat(String formatString, OutputFormat outputFormat) {
132         OutputFormat format = outputFormat;
133         try {
134             format = OutputFormat.valueOf(formatString.toUpperCase());
135         } catch (Exception e) {
136             LOGGER.error("Unrecognized format {}, using default ({})", formatString, outputFormat.toString());
137             // continue
138         }
139         return format;
140     }
141 
142     private static Object call(final Object object, final String methodName,
143             final Object... args) {
144         final boolean isStatic = object instanceof Class<?>;
145         final Class<?> clazz = isStatic ? (Class<?>) object : object.getClass();
146         for (final Method method : clazz.getMethods()) {
147             if (method.getName().equals(methodName)
148                     && isStatic == Modifier.isStatic(method.getModifiers())
149                     && method.getParameterTypes().length == args.length) {
150                 try {
151                     return method.invoke(isStatic ? null : object, args);
152                 } catch (final InvocationTargetException ex) {
153                     Throwables.propagate(ex.getCause());
154                 } catch (final IllegalAccessException ex) {
155                     throw new IllegalArgumentException("Cannot invoke " + method, ex);
156                 }
157             }
158         }
159         throw new IllegalArgumentException("Cannot invoke " + methodName);
160     }
161 
162 }