/*
* Copyright 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.template.soy.examples;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Resources;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.template.soy.SoyFileSet;
import com.google.template.soy.SoyModule;
import com.google.template.soy.data.SoyListData;
import com.google.template.soy.data.SoyMapData;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_AUTOESCAPE_FALSE;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_AUTOESCAPE_TRUE;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_BIDI_SUPPORT;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_CALL_WITHOUT_PARAM;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_CALL_WITH_PARAM;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_CALL_WITH_PARAM_BLOCK;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_COMMENTS;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_DOUBLE_BRACES;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_EXPRESSIONS;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_FOR;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_FOREACH;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_IF;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_LINE_JOINING;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_MSG;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_PRINT;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_PRINT_DIRECTIVES;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_RAW_TEXT_COMMANDS;
import static com.google.template.soy.examples.FeaturesSoyInfo.DEMO_SWITCH;
import com.google.template.soy.msgs.SoyMsgBundle;
import com.google.template.soy.msgs.SoyMsgBundleHandler;
import com.google.template.soy.tofu.SoyTofu;
import com.google.template.soy.xliffmsgplugin.XliffMsgPluginModule;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import java.io.IOException;
import java.net.URL;
/**
* Usage of the features examples.
*
* @author Kai Huang
*/
public class FeaturesUsage {
private FeaturesUsage() {}
/** The string to prepend to the usage message generated by Flags. */
private static final String USAGE_PREFIX =
"Usage:\n" +
"java com.google.template.soy.examples.FeaturesUsage [-locale <locale>]\n";
/** Prefix for XLIFF resource (ends with [locale].xlf). */
private static final String XLIFF_RESOURCE_PREFIX = "examples_translated_";
@Option(name = "-locale",
usage = "The locale to render templates in. The corresponding XLIFF resource " +
XLIFF_RESOURCE_PREFIX + "<locale>.xlf must exist. If not provided, the" +
" messages from the Soy source will be used.")
private String locale = "";
/** Counter for the number of examples written so far. */
private int numExamples = 0;
/**
* Prints the generated HTML to stdout.
* @param args May contain flags.
* @throws IOException If there is an error reading the input files.
*/
public static void main(String[] args) throws IOException {
(new FeaturesUsage()).execMain(args);
}
private void execMain(String[] args) throws IOException {
CmdLineParser cmdLineParser = new CmdLineParser(this);
cmdLineParser.setUsageWidth(100);
try {
cmdLineParser.parseArgument(args);
} catch(CmdLineException cle) {
System.err.println("\nError: " + cle.getMessage() + "\n\n");
System.err.println(USAGE_PREFIX);
cmdLineParser.printUsage(System.err);
System.exit(1);
}
Injector injector = Guice.createInjector(new SoyModule(), new XliffMsgPluginModule());
SoyFileSet.Builder sfsBuilder = injector.getInstance(SoyFileSet.Builder.class);
SoyFileSet sfs = sfsBuilder
.add(Resources.getResource("simple.soy"))
.add(Resources.getResource("features.soy"))
.setCompileTimeGlobals(Resources.getResource("FeaturesUsage_globals.txt"))
.build();
SoyTofu tofu = sfs.compileToTofu().forNamespace("soy.examples.features");
SoyMsgBundle msgBundle;
if (locale.length() > 0) {
// Use translations from an XLIFF file.
SoyMsgBundleHandler msgBundleHandler = injector.getInstance(SoyMsgBundleHandler.class);
URL xliffResource = Resources.getResource(XLIFF_RESOURCE_PREFIX + locale + ".xlf");
msgBundle = msgBundleHandler.createFromResource(xliffResource);
if (msgBundle.getLocaleString() == null) {
throw new IOException(
"Error reading message resource \"" + XLIFF_RESOURCE_PREFIX + locale + ".xlf\".");
}
} else {
// Use the messages from the Soy source files.
msgBundle = null;
}
// Note: In the examples below, I sometimes use the version of render() that takes a SoyMapData
// and sometimes use the version that takes a Map<String, ?>. They both work. The version that
// takes a SoyMapData is more efficient if you need to reuse the same template data object for
// multiple calls of render() (because the version that takes a Map<String, ?> internally
// converts it to a new SoyMapData on every call).
writeExampleHeader("demoComments");
System.out.println(tofu.newRenderer(DEMO_COMMENTS).setMsgBundle(msgBundle).render());
writeExampleHeader("demoLineJoining");
System.out.println(tofu.newRenderer(DEMO_LINE_JOINING).setMsgBundle(msgBundle).render());
writeExampleHeader("demoRawTextCommands");
System.out.println(tofu.newRenderer(DEMO_RAW_TEXT_COMMANDS).setMsgBundle(msgBundle).render());
writeExampleHeader("demoPrint");
System.out.println(tofu.newRenderer(DEMO_PRINT)
.setData(new SoyMapData(DEMO_PRINT.BOO, "Boo!", DEMO_PRINT.TWO, 2))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoPrintDirectives");
System.out.println(tofu.newRenderer(DEMO_PRINT_DIRECTIVES)
.setData(ImmutableMap.of(DEMO_PRINT_DIRECTIVES.LONG_VAR_NAME,
"thisIsSomeRidiculouslyLongVariableName",
DEMO_PRINT_DIRECTIVES.ELEMENT_ID, "my_element_id",
DEMO_PRINT_DIRECTIVES.CSS_CLASS, "my_css_class"))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoAutoescapeTrue");
System.out.println(tofu.newRenderer(DEMO_AUTOESCAPE_TRUE)
.setData(new SoyMapData(DEMO_AUTOESCAPE_TRUE.ITALIC_HTML, "<i>italic</i>"))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoAutoescapeFalse");
System.out.println(tofu.newRenderer(DEMO_AUTOESCAPE_FALSE)
.setData(new SoyMapData(DEMO_AUTOESCAPE_FALSE.ITALIC_HTML, "<i>italic</i>"))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoMsg");
System.out.println(tofu.newRenderer(DEMO_MSG)
.setData(ImmutableMap.of(DEMO_MSG.NAME, "Ed",
DEMO_MSG.LABS_URL, "http://labs.google.com"))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoIf");
System.out.println(tofu.newRenderer(DEMO_IF)
.setData(new SoyMapData("pi", 3.14159)).setMsgBundle(msgBundle).render());
System.out.println(tofu.newRenderer(DEMO_IF)
.setData(new SoyMapData("pi", 2.71828)).setMsgBundle(msgBundle).render());
System.out.println(tofu.newRenderer(DEMO_IF)
.setData(new SoyMapData("pi", 1.61803)).setMsgBundle(msgBundle).render());
writeExampleHeader("demoSwitch");
System.out.println(tofu.newRenderer(DEMO_SWITCH)
.setData(ImmutableMap.of("name", "Fay")).setMsgBundle(msgBundle).render());
System.out.println(tofu.newRenderer(DEMO_SWITCH)
.setData(ImmutableMap.of("name", "Go")).setMsgBundle(msgBundle).render());
System.out.println(tofu.newRenderer(DEMO_SWITCH)
.setData(ImmutableMap.of("name", "Hal")).setMsgBundle(msgBundle).render());
System.out.println(tofu.newRenderer(DEMO_SWITCH)
.setData(ImmutableMap.of("name", "Ivy")).setMsgBundle(msgBundle).render());
writeExampleHeader("demoForeach");
SoyListData persons = new SoyListData();
persons.add(new SoyMapData("name", "Jen", "numWaffles", 1));
persons.add(new SoyMapData("name", "Kai", "numWaffles", 3));
persons.add(new SoyMapData("name", "Lex", "numWaffles", 1));
persons.add(new SoyMapData("name", "Mel", "numWaffles", 2));
System.out.println(tofu.newRenderer(DEMO_FOREACH)
.setData(new SoyMapData(DEMO_FOREACH.PERSONS, persons))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoFor");
System.out.println(tofu.newRenderer(DEMO_FOR)
.setData(new SoyMapData(DEMO_FOR.NUM_LINES, 3))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoCallWithoutParam");
System.out.println(tofu.newRenderer(DEMO_CALL_WITHOUT_PARAM)
.setData(new SoyMapData(
DEMO_CALL_WITHOUT_PARAM.NAME, "Neo",
DEMO_CALL_WITHOUT_PARAM.TRIP_INFO,
new SoyMapData("name", "Neo", "destination", "The Matrix")))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoCallWithParam");
System.out.println(tofu.newRenderer(DEMO_CALL_WITH_PARAM)
.setData(ImmutableMap.of(
DEMO_CALL_WITH_PARAM.NAME, "Oz",
DEMO_CALL_WITH_PARAM.COMPANION_NAME, "Pip",
DEMO_CALL_WITH_PARAM.DESTINATIONS,
ImmutableList.of("Gillikin Country", "Munchkin Country",
"Quadling Country", "Winkie Country")))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoCallWithParamBlock");
System.out.println(tofu.newRenderer(DEMO_CALL_WITH_PARAM_BLOCK)
.setData(new SoyMapData(DEMO_CALL_WITH_PARAM_BLOCK.NAME, "Quo"))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoExpressions");
SoyListData students = new SoyListData();
students.add(new SoyMapData("name", "Rob", "major", "Physics", "year", 1999));
students.add(new SoyMapData("name", "Sha", "major", "Finance", "year", 1980));
students.add(new SoyMapData("name", "Tim", "major", "Engineering", "year", 2005));
students.add(new SoyMapData("name", "Uma", "major", "Biology", "year", 1972));
System.out.println(tofu.newRenderer(DEMO_EXPRESSIONS)
.setData(new SoyMapData(DEMO_EXPRESSIONS.STUDENTS, students,
DEMO_EXPRESSIONS.CURRENT_YEAR, 2008))
.setMsgBundle(msgBundle)
.render());
writeExampleHeader("demoDoubleBraces");
System.out.println(tofu.newRenderer(DEMO_DOUBLE_BRACES)
.setData(ImmutableMap.of(DEMO_DOUBLE_BRACES.SET_NAME, "prime numbers",
DEMO_DOUBLE_BRACES.SET_MEMBERS,
ImmutableList.of(2, 3, 5, 7, 11, 13)))
.setMsgBundle(msgBundle)
.render());
// The Hebrew in the following example comes out as question marks in the output because
// System.out (and by default stdout generally) is set up to use a Latin encoding. To see
// this really in action, run the Javascript example.
writeExampleHeader("demoBidiSupport");
System.out.println(tofu.newRenderer(DEMO_BIDI_SUPPORT)
.setData(ImmutableMap.of(DEMO_BIDI_SUPPORT.TITLE, "2008: A BiDi Odyssey",
DEMO_BIDI_SUPPORT.AUTHOR, "John Doe, Esq.",
DEMO_BIDI_SUPPORT.YEAR, "1973",
DEMO_BIDI_SUPPORT.KEYWORDS,
ImmutableList.of(
"Bi(Di)",
"2008 (\u05E9\u05E0\u05D4)",
"2008 (year)")))
.setMsgBundle(msgBundle)
.render());
}
/**
* Private helper to write the header for each example.
* @param exampleName The name of the example.
*/
private void writeExampleHeader(String exampleName) {
numExamples++;
System.out.println(
"--------------------------------------------------------------------------------");
System.out.printf("[%d. %s]\n", numExamples, exampleName);
}
}