com.google.gxp.compiler.cli..svn.text-base.GxpcFlags.svn-base Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of google-gxp Show documentation
Show all versions of google-gxp Show documentation
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();
}
}