All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gxp.compiler.cli..svn.text-base.GxpcFlags.svn-base Maven / Gradle / Ivy

Go to download

Google XML Pages (GXP) is a templating system used to generate XML/SGML markup (most often HTML).

The newest version!
/*
 * Copyright (C) 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.gxp.compiler.cli;

import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.io.CharStreams;
import com.google.gxp.compiler.Configuration;
import com.google.gxp.compiler.Phase;
import com.google.gxp.compiler.alerts.Alert.Severity;
import com.google.gxp.compiler.alerts.AlertPolicy;
import com.google.gxp.compiler.alerts.ConfigurableAlertPolicy;
import com.google.gxp.compiler.base.OutputLanguage;
import com.google.gxp.compiler.codegen.CodeGeneratorFactory;
import com.google.gxp.compiler.codegen.DefaultCodeGeneratorFactory;
import com.google.gxp.compiler.fs.FileRef;
import com.google.gxp.compiler.fs.FileSystem;
import com.google.gxp.compiler.fs.SourcePathFileSystem;
import com.google.gxp.compiler.i18ncheck.UnextractableContentAlert;
import com.google.gxp.compiler.parser.FileSystemEntityResolver;
import com.google.gxp.compiler.parser.SourceEntityResolver;

import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.util.*;

import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;

/**
 * The GXP compiler, "gxpc". The command line interface for generating code and
 * XMB files from GXP files.
 */
class GxpcFlags implements Configuration {
  private final CommandLine commandLine;
  private final ImmutableSet sourceFiles;
  private final ImmutableSet schemaFiles;
  private final ImmutableSet outputLanguages;
  private final DefaultCodeGeneratorFactory codeGeneratorFactory;
  private final ImmutableSet allowedOutputFiles;
  private final FileRef dependencyFile;
  private final FileRef propertiesFile;
  private final boolean isVerboseEnabled;
  private final boolean isDebugEnabled;
  private final AlertPolicy alertPolicy;
  private final ImmutableSortedSet dotPhases;
  private final SourceEntityResolver sourceEntityResolver;

  /**
   * Creates an instance of the compiler based on command-line arguments.
   *
   * @param fs underlying {@code FileSystem} that filenames in {@code args}
   * refer to
   * @param defaultDir default directory for source and output dirs
   * @param args command-line arguments. See HELP_* variables
   * defined in {@link GxpcFlags} for accepted flags
   * @throws Flags.UsageError if there is an error parsing the command line
   * arguments
   */
  GxpcFlags(FileSystem fs, FileRef defaultDir, String... args)
      throws CmdLineException, IOException {

    // If there is only one argument, and it starts with an '@', then treat it
    // as an options file, relative to the current working directory.
    if ((args.length == 1) && (args[0].startsWith("@"))) {
      FileRef optionsFile = defaultDir.join(args[0].substring(1));
      Reader in = optionsFile.openReader(Charsets.UTF_8);
      List lines = CharStreams.readLines(in);
      in.close();
      List parsedTokens = Lists.newArrayList();
      for (String line : lines) {
        for (String token : line.trim().split("\\s+")) {
          if (token.length() > 0) {
            parsedTokens.add(token);
          }
        }
      }
      args = parsedTokens.toArray(new String[parsedTokens.size()]);
    }

    commandLine = new CommandLine(args);

    Set underlyingInputFiles = getFileRefs(fs, commandLine.trailingArgs);

    FileRef outputDir = (commandLine.FLAG_dir == null)
        ? defaultDir : fs.parseFilename(commandLine.FLAG_dir);

    List sourcePaths = (commandLine.FLAG_source == null)
        ? Collections.singletonList(defaultDir)
        : fs.parseFilenameList(commandLine.FLAG_source);

    SourcePathFileSystem sourcePathFs = new SourcePathFileSystem(fs,
                                                                 sourcePaths,
                                                                 underlyingInputFiles,
                                                                 outputDir);

    sourceFiles = ImmutableSet.copyOf(sourcePathFs.getSourceFileRefs());
    schemaFiles = getFileRefs(fs, commandLine.FLAG_schema);

    // Compute Output Languages
    Set tmpOutputLanguages = EnumSet.noneOf(OutputLanguage.class);
    for (String outputLanguage : commandLine.FLAG_output_language) {
      tmpOutputLanguages.add(OutputLanguage.valueOf(outputLanguage.toUpperCase()));
    }
    outputLanguages = ImmutableSet.copyOf(tmpOutputLanguages);

    allowedOutputFiles = getFileRefs(sourcePathFs, commandLine.FLAG_output);

    alertPolicy = computeAlertPolicy(commandLine.FLAG_warn, commandLine.FLAG_error);

    // Compute Dependency File
    dependencyFile = (commandLine.FLAG_depend == null)
        ? null : fs.parseFilename(commandLine.FLAG_depend);

    // Compute Properties File
    propertiesFile = (commandLine.FLAG_output_properties
                      && commandLine.FLAG_message_source != null)
        ? outputDir.join(
            "/" + commandLine.FLAG_message_source.replace(".", "/") + "_en.properties")
        : null;

    isVerboseEnabled = commandLine.FLAG_verbose;
    isDebugEnabled = commandLine.FLAG_g;

    // Compute Dot Phases
    dotPhases = computeDotPhases(commandLine.getParser(), commandLine.FLAG_dot);

    // Compute SourceEntityResolver
    // use the sourcePathFs so that gxp:///foo/bar is resolved in a way that
    // includes both source files and genfiles
    sourceEntityResolver = new FileSystemEntityResolver(sourcePathFs);

    // Compute CodeGeneratorFactory (Always do this last)
    codeGeneratorFactory = new DefaultCodeGeneratorFactory();
    codeGeneratorFactory.setRuntimeMessageSource(commandLine.FLAG_message_source);
    codeGeneratorFactory.setDynamicModeEnabled(commandLine.FLAG_dynamic);
    codeGeneratorFactory.setSourceFiles(getSourceFiles());
    codeGeneratorFactory.setSchemaFiles(getSchemaFiles());
    codeGeneratorFactory.setSourcePaths(sourcePaths);
    codeGeneratorFactory.setAlertPolicy(getAlertPolicy());
  }

  public boolean showHelp() {
    return commandLine.FLAG_help;
  }

  public void printHelp(Appendable out) throws IOException {
    out.append(commandLine.getUsage());
  }

  ////////////////////////////////////////////////////////////////////////////////
  // Supplemental Computation Functions
  ////////////////////////////////////////////////////////////////////////////////

  /**
   * Iterate over an {@code Iterable} of flags treating each as a filename in the
   * supplied {@link FileSystem}.
   *
   * @return an {@link ImmutableSet} of the results.
   */
  private static ImmutableSet getFileRefs(FileSystem fs, Iterable filenames) {
    Set result = Sets.newHashSet();
    for (String filename : filenames) {
      result.add(fs.parseFilename(filename));
    }
    return ImmutableSet.copyOf(result);
  }

  // TODO(laurence): add more general support for AlertPolicy configuration
  private static final AlertPolicy computeAlertPolicy(List warnFlags,
                                                      List errorFlags) {
    ConfigurableAlertPolicy result = new ConfigurableAlertPolicy();
    configureAlertPolicy(result, warnFlags,  Severity.WARNING);
    configureAlertPolicy(result, errorFlags, Severity.ERROR);
    if (warnFlags.contains("error")) {
      result.setTreatWarningsAsErrors(true);
    }

    return result;
  }

  private static final void configureAlertPolicy(ConfigurableAlertPolicy alertPolicy,
                                                 List flags,
                                                 Severity severity) {
    if (flags.contains("i18n")) {
      alertPolicy.setSeverity(UnextractableContentAlert.class, severity);
    }
  }

  private static ImmutableSortedSet computeDotPhases(CmdLineParser parser,
                                                            List phaseNames)
      throws CmdLineException {
    SortedSet result = Sets.newTreeSet();
    if (phaseNames.contains("*")) {
      result.addAll(Arrays.asList(Phase.values()));
    } else {
      for (String phaseName : phaseNames) {
        phaseName = phaseName.trim();
        if (phaseName.length() > 0) {
          phaseName = phaseName.toUpperCase().replace("-", "_");
          Phase phase;
          try {
            phase = Phase.valueOf(phaseName);
          } catch (IllegalArgumentException iax) {
            throw new CmdLineException(parser, "illegal phase name in --dot flag: " + phaseName);
          }
          result.add(phase);
        }
      }
    }
    return ImmutableSortedSet.copyOfSorted(result);
  }

  ////////////////////////////////////////////////////////////////////////////////
  // Configuration Implementation
  ////////////////////////////////////////////////////////////////////////////////

  public Set getSourceFiles() {
    return sourceFiles;
  }

  public Set getSchemaFiles() {
    return schemaFiles;
  }

  public Set getOutputLanguages() {
    return outputLanguages;
  }

  public long getCompilationVersion() {
    return 0;
  }

  public CodeGeneratorFactory getCodeGeneratorFactory() {
    return codeGeneratorFactory;
  }

  public Set getAllowedOutputFiles() {
    return allowedOutputFiles;
  }

  public FileRef getDependencyFile() {
    return dependencyFile;
  }

  public FileRef getPropertiesFile() {
    return propertiesFile;
  }

  public boolean isVerboseEnabled() {
    return isVerboseEnabled;
  }

  public boolean isDebugEnabled() {
    return isDebugEnabled;
  }

  public AlertPolicy getAlertPolicy() {
    return alertPolicy;
  }

  public SortedSet getDotPhases() {
    return dotPhases;
  }

  public SourceEntityResolver getEntityResolver() {
    return sourceEntityResolver;
  }

  ////////////////////////////////////////////////////////////////////////////////
  // Command Line
  ////////////////////////////////////////////////////////////////////////////////

  /**
   * Bucket for holding the output of flags parsing. It doesn't do any fancy
   * processing of the flags.
   */
  private static class CommandLine {
    private final CmdLineParser parser;

    private CommandLine(String[] args) throws CmdLineException {
      parser = new CmdLineParser(this);
      parser.parseArgument(args);
    }

    public CmdLineParser getParser() {
      return parser;
    }

    public String getUsage() {
      StringWriter sw = new StringWriter();
      sw.append("Usage: gxpc [flags...] [args...]\n");
      parser.printUsage(sw, null);
      return sw.toString();
    }

    @Argument
    public List trailingArgs = Lists.newArrayList();

    @Option(name = "--help",
            usage = "display this help message")
    public boolean FLAG_help = false;

    @Option(name = "--dir",
            usage = "output directory")
    public String FLAG_dir = null;

    @Option(name = "--schema",
            usage = "a schema file used for compilation; can be repeated.")
    public List FLAG_schema = Lists.newArrayList();

    @Option(name = "--output_language",
            usage = "output files for this language; can be repeated.")
    public List FLAG_output_language = Lists.newArrayList();

    @Option(name = "--output",
            usage = "output this file; can be repeated. If not specified,\n"
                  + "all files will be output.")
    public List FLAG_output = Lists.newArrayList();

    @Option(name = "--warn",
            usage = "Sets warning options. VAL can be one of:\n"
                  + "i18n (enable i18n warnings),\n"
                  + "error (warnings are errors)")
    public List FLAG_warn = Lists.newArrayList();

    @Option(name = "--error",
            usage = "Sets error options. VAL can be one of:\n"
                  + "i18n (enable i18n errors)")
    public List FLAG_error = Lists.newArrayList();

    @Option(name = "--source",
            usage = "base directory for source")
    public String FLAG_source = null;

    @Option(name = "--dynamic",
            usage = "indicate dynamic mode")
    public boolean FLAG_dynamic = false;

    @Option(name = "--output_properties",
            usage = "indicates that gxpc should output a properties file")
    public boolean FLAG_output_properties = false;

    @Option(name = "--message_source",
            usage = "Message source for retrieving messages at runtime.\n"
                  + "eg: com.google.foo.bar_messages")
    public String FLAG_message_source = null;

    @Option(name = "--depend",
            usage = "location of dependency info file; enables dependency\n"
                  + "checking")
    public String FLAG_depend = null;

    @Option(name = "--verbose",
            usage = "enable verbose mode")
    public boolean FLAG_verbose = false;

    @Option(name = "--g",
            usage = "include debugging comments in HTML output")
    public boolean FLAG_g = false;

    @Option(name = "--dot",
            usage = "phase to produce graphviz \"dot\" output for;\n"
                  + "can be repeated (useful for debugging compiler)")
    public List FLAG_dot = Lists.newArrayList();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy