YARN-9279. Remove the old hamlet package. (#2986)

Signed-off-by: Takanobu Asanuma <tasanuma@apache.org>
This commit is contained in:
Akira Ajisaka 2021-05-21 12:40:50 +09:00 committed by GitHub
parent 0d59500e8c
commit c8073811b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 135 additions and 34697 deletions

View File

@ -378,34 +378,4 @@
</plugin>
</plugins>
</build>
<!-- TODO: Remove this profile when hamlet was removed. -->
<profiles>
<profile>
<id>java9</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>org/apache/hadoop/yarn/webapp/hamlet/**</exclude>
</excludes>
<testExcludes>
<exclude>org/apache/hadoop/yarn/webapp/hamlet/**</exclude>
</testExcludes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<excludePackageNames>org.apache.hadoop.yarn.webapp.hamlet</excludePackageNames>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -1,451 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.yarn.webapp.hamlet;
import org.apache.hadoop.thirdparty.com.google.common.collect.Sets;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.yarn.webapp.WebAppException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Generates a specific hamlet implementation class from a spec class
* using a generic hamlet implementation class.
* @deprecated Use org.apache.hadoop.yarn.webapp.hamlet2 package instead.
*/
@Deprecated
@InterfaceAudience.LimitedPrivate({"YARN", "MapReduce"})
public class HamletGen {
static final Logger LOG = LoggerFactory.getLogger(HamletGen.class);
static final Options opts = new Options();
static {
opts.addOption("h", "help", false, "Print this help message").
addOption("s", "spec-class", true,
"The class that holds the spec interfaces. e.g. HamletSpec").
addOption("i", "impl-class", true,
"An implementation class. e.g. HamletImpl").
addOption("o", "output-class", true, "Output class name").
addOption("p", "output-package", true, "Output package name");
};
static final Pattern elementRegex = Pattern.compile("^[A-Z][A-Z0-9]*$");
int bytes = 0;
PrintWriter out;
final Set<String> endTagOptional = Sets.newHashSet();
final Set<String> inlineElements = Sets.newHashSet();
Class<?> top; // html top-level interface
String hamlet; // output class simple name;
boolean topMode;
/**
* Generate a specific Hamlet implementation from a spec.
* @param specClass holds hamlet interfaces. e.g. {@link HamletSpec}
* @param implClass a generic hamlet implementation. e.g. {@link HamletImpl}
* @param outputName name of the output class. e.g. {@link Hamlet}
* @param outputPkg package name of the output class.
* @throws IOException
*/
public void generate(Class<?> specClass, Class<?> implClass,
String outputName, String outputPkg) throws IOException {
LOG.info("Generating {} using {} and {}", new Object[]{outputName,
specClass, implClass});
out = new PrintWriter(outputName +".java", "UTF-8");
hamlet = basename(outputName);
String pkg = pkgName(outputPkg, implClass.getPackage().getName());
puts(0, "// Generated by HamletGen. Do NOT edit!\n",
"package ", pkg, ";\n",
"import java.io.PrintWriter;\n",
"import java.util.EnumSet;\n",
"import static java.util.EnumSet.*;\n",
"import static ", implClass.getName(), ".EOpt.*;\n",
"import org.apache.hadoop.yarn.webapp.SubView;");
String implClassName = implClass.getSimpleName();
if (!implClass.getPackage().getName().equals(pkg)) {
puts(0, "import ", implClass.getName(), ';');
}
puts(0, "\n",
"public class ", hamlet, " extends ", implClassName,
" implements ", specClass.getSimpleName(), "._Html {\n",
" public ", hamlet, "(PrintWriter out, int nestLevel,",
" boolean wasInline) {\n",
" super(out, nestLevel, wasInline);\n",
" }\n\n", // inline is context sensitive
" static EnumSet<EOpt> opt(boolean endTag, boolean inline, ",
"boolean pre) {\n",
" EnumSet<EOpt> opts = of(ENDTAG);\n",
" if (!endTag) opts.remove(ENDTAG);\n",
" if (inline) opts.add(INLINE);\n",
" if (pre) opts.add(PRE);\n",
" return opts;\n",
" }");
initLut(specClass);
genImpl(specClass, implClassName, 1);
LOG.info("Generating {} methods", hamlet);
genMethods(hamlet, top, 1);
puts(0, "}");
out.close();
LOG.info("Wrote {} bytes to {}.java", bytes, outputName);
}
String basename(String path) {
return path.substring(path.lastIndexOf('/') + 1);
}
String pkgName(String pkg, String defaultPkg) {
if (pkg == null || pkg.isEmpty()) return defaultPkg;
return pkg;
}
void initLut(Class<?> spec) {
endTagOptional.clear();
inlineElements.clear();
for (Class<?> cls : spec.getClasses()) {
Annotation a = cls.getAnnotation(HamletSpec.Element.class);
if (a != null && !((HamletSpec.Element) a).endTag()) {
endTagOptional.add(cls.getSimpleName());
}
if (cls.getSimpleName().equals("Inline")) {
for (Method method : cls.getMethods()) {
String retName = method.getReturnType().getSimpleName();
if (isElement(retName)) {
inlineElements.add(retName);
}
}
}
}
}
void genImpl(Class<?> spec, String implClassName, int indent) {
String specName = spec.getSimpleName();
for (Class<?> cls : spec.getClasses()) {
String className = cls.getSimpleName();
if (cls.isInterface()) {
genFactoryMethods(cls, indent);
}
if (isElement(className)) {
LOG.info("Generating class {}<T>", className);
puts(indent, "\n",
"public class ", className, "<T extends _>",
" extends EImp<T> implements ", specName, ".", className, " {\n",
" public ", className, "(String name, T parent,",
" EnumSet<EOpt> opts) {\n",
" super(name, parent, opts);\n",
" }");
genMethods(className, cls, indent + 1);
puts(indent, "}");
} else if (className.equals("_Html")) {
top = cls;
}
}
}
void genFactoryMethods(Class<?> cls, int indent) {
for (Method method : cls.getDeclaredMethods()) {
String retName = method.getReturnType().getSimpleName();
String methodName = method.getName();
if (methodName.charAt(0) == '$') continue;
if (isElement(retName) && method.getParameterTypes().length == 0) {
genFactoryMethod(retName, methodName, indent);
}
}
}
void genMethods(String className, Class<?> cls, int indent) {
topMode = (top != null && cls.equals(top));
for (Method method : cls.getMethods()) {
String retName = method.getReturnType().getSimpleName();
if (method.getName().charAt(0) == '$') {
genAttributeMethod(className, method, indent);
} else if (isElement(retName)) {
genNewElementMethod(className, method, indent);
} else {
genCurElementMethod(className, method, indent);
}
}
}
void genAttributeMethod(String className, Method method, int indent) {
String methodName = method.getName();
String attrName = methodName.substring(1).replace('_', '-');
Type[] params = method.getGenericParameterTypes();
echo(indent, "\n",
"@Override\n",
"public ", className, topMode ? " " : "<T> ", methodName, "(");
if (params.length == 0) {
puts(0, ") {");
puts(indent,
" addAttr(\"", attrName, "\", null);\n",
" return this;\n", "}");
} else if (params.length == 1) {
String typeName = getTypeName(params[0]);
puts(0, typeName, " value) {");
if (typeName.equals("EnumSet<LinkType>")) {
puts(indent,
" addRelAttr(\"", attrName, "\", value);\n",
" return this;\n", "}");
} else if (typeName.equals("EnumSet<Media>")) {
puts(indent,
" addMediaAttr(\"", attrName, "\", value);\n",
" return this;\n", "}");
} else {
puts(indent,
" addAttr(\"", attrName, "\", value);\n",
" return this;\n", "}");
}
} else {
throwUnhandled(className, method);
}
}
String getTypeName(Type type) {
if (type instanceof Class<?>) {
return ((Class<?>)type).getSimpleName();
}
ParameterizedType pt = (ParameterizedType) type;
return ((Class<?>)pt.getRawType()).getSimpleName() +"<"+
((Class<?>)pt.getActualTypeArguments()[0]).getSimpleName() +">";
}
void genFactoryMethod(String retName, String methodName, int indent) {
puts(indent, "\n",
"private <T extends _> ", retName, "<T> ", methodName,
"_(T e, boolean inline) {\n",
" return new ", retName, "<T>(\"", StringUtils.toLowerCase(retName),
"\", e, opt(", !endTagOptional.contains(retName), ", inline, ",
retName.equals("PRE"), ")); }");
}
void genNewElementMethod(String className, Method method, int indent) {
String methodName = method.getName();
String retName = method.getReturnType().getSimpleName();
Class<?>[] params = method.getParameterTypes();
echo(indent, "\n",
"@Override\n",
"public ", retName, "<", className, topMode ? "> " : "<T>> ",
methodName, "(");
if (params.length == 0) {
puts(0, ") {");
puts(indent,
topMode ? "" : " closeAttrs();\n",
" return ", StringUtils.toLowerCase(retName), "_" + "(this, ",
isInline(className, retName), ");\n", "}");
} else if (params.length == 1) {
puts(0, "String selector) {");
puts(indent,
" return setSelector(", methodName, "(), selector);\n", "}");
} else {
throwUnhandled(className, method);
}
}
boolean isInline(String container, String className) {
if ((container.equals("BODY") || container.equals(hamlet) ||
container.equals("HEAD") || container.equals("HTML")) &&
(className.equals("INS") || className.equals("DEL") ||
className.equals("SCRIPT"))) {
return false;
}
return inlineElements.contains(className);
}
void genCurElementMethod(String className, Method method, int indent) {
String methodName = method.getName();
Class<?>[] params = method.getParameterTypes();
if (topMode || params.length > 0) {
echo(indent, "\n",
"@Override\n",
"public ", className, topMode ? " " : "<T> ", methodName, "(");
}
if (params.length == 0) {
if (topMode) {
puts(0, ") {");
puts(indent, " return this;\n", "}");
}
} else if (params.length == 1) {
if (methodName.equals("base")) {
puts(0, "String href) {");
puts(indent,
" return base().$href(href)._();\n", "}");
} else if (methodName.equals("script")) {
puts(0, "String src) {");
puts(indent,
" return setScriptSrc(script(), src)._();\n", "}");
} else if (methodName.equals("style")) {
puts(0, "Object... lines) {");
puts(indent,
" return style().$type(\"text/css\")._(lines)._();\n", "}");
} else if (methodName.equals("img")) {
puts(0, "String src) {");
puts(indent,
" return ", methodName, "().$src(src)._();\n", "}");
} else if (methodName.equals("br") || methodName.equals("hr") ||
methodName.equals("col")) {
puts(0, "String selector) {");
puts(indent,
" return setSelector(", methodName, "(), selector)._();\n", "}");
} else if (methodName.equals("link")) {
puts(0, "String href) {");
puts(indent,
" return setLinkHref(", methodName, "(), href)._();\n", "}");
} else if (methodName.equals("_")) {
if (params[0].getSimpleName().equals("Class")) {
puts(0, "Class<? extends SubView> cls) {");
puts(indent,
" ", topMode ? "subView" : "_v", "(cls);\n",
" return this;\n", "}");
} else {
puts(0, "Object... lines) {");
puts(indent,
" _p(", needsEscaping(className), ", lines);\n",
" return this;\n", "}");
}
} else if (methodName.equals("_r")) {
puts(0, "Object... lines) {");
puts(indent,
" _p(false, lines);\n",
" return this;\n", "}");
} else {
puts(0, "String cdata) {");
puts(indent,
" return ", methodName, "()._(cdata)._();\n", "}");
}
} else if (params.length == 2) {
if (methodName.equals("meta")) {
puts(0, "String name, String content) {");
puts(indent,
" return meta().$name(name).$content(content)._();\n", "}");
} else if (methodName.equals("meta_http")) {
puts(0, "String header, String content) {");
puts(indent,
" return meta().$http_equiv(header).$content(content)._();\n",
"}");
} else if (methodName.equals("a")) {
puts(0, "String href, String anchorText) {");
puts(indent,
" return a().$href(href)._(anchorText)._();\n", "}");
} else if (methodName.equals("bdo")) {
puts(0, "Dir dir, String cdata) {");
puts(indent, " return bdo().$dir(dir)._(cdata)._();\n", "}");
} else if (methodName.equals("label")) {
puts(0, "String forId, String cdata) {");
puts(indent, " return label().$for(forId)._(cdata)._();\n", "}");
} else if (methodName.equals("param")) {
puts(0, "String name, String value) {");
puts(indent,
" return param().$name(name).$value(value)._();\n", "}");
} else {
puts(0, "String selector, String cdata) {");
puts(indent,
" return setSelector(", methodName,
"(), selector)._(cdata)._();\n", "}");
}
} else if (params.length == 3) {
if (methodName.equals("a")) {
puts(0, "String selector, String href, String anchorText) {");
puts(indent,
" return setSelector(a(), selector)",
".$href(href)._(anchorText)._();\n", "}");
}
} else {
throwUnhandled(className, method);
}
}
static boolean needsEscaping(String eleName) {
return !eleName.equals("SCRIPT") && !eleName.equals("STYLE");
}
static void throwUnhandled(String className, Method method) {
throw new WebAppException("Unhandled " + className + "#" + method);
}
void echo(int indent, Object... args) {
String prev = null;
for (Object o : args) {
String s = String.valueOf(o);
if (!s.isEmpty() && !s.equals("\n") &&
(prev == null || prev.endsWith("\n"))) {
indent(indent);
}
prev = s;
out.print(s);
bytes += s.length();
}
}
void indent(int indent) {
for (int i = 0; i < indent; ++i) {
out.print(" ");
bytes += 2;
}
}
void puts(int indent, Object... args) {
echo(indent, args);
out.println();
++bytes;
}
boolean isElement(String s) {
return elementRegex.matcher(s).matches();
}
public static void main(String[] args) throws Exception {
CommandLine cmd = new GnuParser().parse(opts, args);
if (cmd.hasOption("help")) {
new HelpFormatter().printHelp("Usage: hbgen [OPTIONS]", opts);
return;
}
// defaults
Class<?> specClass = HamletSpec.class;
Class<?> implClass = HamletImpl.class;
String outputClass = "HamletTmp";
String outputPackage = implClass.getPackage().getName();
if (cmd.hasOption("spec-class")) {
specClass = Class.forName(cmd.getOptionValue("spec-class"));
}
if (cmd.hasOption("impl-class")) {
implClass = Class.forName(cmd.getOptionValue("impl-class"));
}
if (cmd.hasOption("output-class")) {
outputClass = cmd.getOptionValue("output-class");
}
if (cmd.hasOption("output-package")) {
outputPackage = cmd.getOptionValue("output-package");
}
new HamletGen().generate(specClass, implClass, outputClass, outputPackage);
}
}

View File

@ -1,387 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.yarn.webapp.hamlet;
import org.apache.hadoop.thirdparty.com.google.common.base.Joiner;
import static org.apache.hadoop.thirdparty.com.google.common.base.Preconditions.*;
import org.apache.hadoop.thirdparty.com.google.common.base.Splitter;
import org.apache.hadoop.thirdparty.com.google.common.collect.Iterables;
import java.io.PrintWriter;
import java.util.EnumSet;
import static java.util.EnumSet.*;
import java.util.Iterator;
import static org.apache.commons.text.StringEscapeUtils.*;
import static org.apache.hadoop.yarn.webapp.hamlet.HamletImpl.EOpt.*;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.yarn.webapp.SubView;
import org.apache.hadoop.yarn.webapp.WebAppException;
/**
* A simple unbuffered generic hamlet implementation.
*
* Zero copy but allocation on every element, which could be
* optimized to use a thread-local element pool.
*
* Prints HTML as it builds. So the order is important.
* @deprecated Use org.apache.hadoop.yarn.webapp.hamlet2 package instead.
*/
@Deprecated
@InterfaceAudience.Private
public class HamletImpl extends HamletSpec {
private static final String INDENT_CHARS = " ";
private static final Splitter SS = Splitter.on('.').
omitEmptyStrings().trimResults();
private static final Joiner SJ = Joiner.on(' ');
private static final Joiner CJ = Joiner.on(", ");
static final int S_ID = 0;
static final int S_CLASS = 1;
int nestLevel;
int indents; // number of indent() called. mostly for testing.
private final PrintWriter out;
private final StringBuilder sb = new StringBuilder(); // not shared
private boolean wasInline = false;
/**
* Element options. (whether it needs end tag, is inline etc.)
*/
public enum EOpt {
/** needs end(close) tag */
ENDTAG,
/** The content is inline */
INLINE,
/** The content is preformatted */
PRE
};
/**
* The base class for elements
* @param <T> type of the parent (containing) element for the element
*/
public class EImp<T extends _> implements _Child {
private final String name;
private final T parent; // short cut for parent element
private final EnumSet<EOpt> opts; // element options
private boolean started = false;
private boolean attrsClosed = false;
EImp(String name, T parent, EnumSet<EOpt> opts) {
this.name = name;
this.parent = parent;
this.opts = opts;
}
@Override
public T _() {
closeAttrs();
--nestLevel;
printEndTag(name, opts);
return parent;
}
protected void _p(boolean quote, Object... args) {
closeAttrs();
for (Object s : args) {
if (!opts.contains(PRE)) {
indent(opts);
}
out.print(quote ? escapeHtml4(String.valueOf(s))
: String.valueOf(s));
if (!opts.contains(INLINE) && !opts.contains(PRE)) {
out.println();
}
}
}
protected void _v(Class<? extends SubView> cls) {
closeAttrs();
subView(cls);
}
protected void closeAttrs() {
if (!attrsClosed) {
startIfNeeded();
++nestLevel;
out.print('>');
if (!opts.contains(INLINE) && !opts.contains(PRE)) {
out.println();
}
attrsClosed = true;
}
}
protected void addAttr(String name, String value) {
checkState(!attrsClosed, "attribute added after content");
startIfNeeded();
printAttr(name, value);
}
protected void addAttr(String name, Object value) {
addAttr(name, String.valueOf(value));
}
protected void addMediaAttr(String name, EnumSet<Media> media) {
// 6.13 comma-separated list
addAttr(name, CJ.join(media));
}
protected void addRelAttr(String name, EnumSet<LinkType> types) {
// 6.12 space-separated list
addAttr(name, SJ.join(types));
}
private void startIfNeeded() {
if (!started) {
printStartTag(name, opts);
started = true;
}
}
protected void _inline(boolean choice) {
if (choice) {
opts.add(INLINE);
} else {
opts.remove(INLINE);
}
}
protected void _endTag(boolean choice) {
if (choice) {
opts.add(ENDTAG);
} else {
opts.remove(ENDTAG);
}
}
protected void _pre(boolean choice) {
if (choice) {
opts.add(PRE);
} else {
opts.remove(PRE);
}
}
}
public class Generic<T extends _> extends EImp<T> implements PCData {
Generic(String name, T parent, EnumSet<EOpt> opts) {
super(name, parent, opts);
}
public Generic<T> _inline() {
super._inline(true);
return this;
}
public Generic<T> _noEndTag() {
super._endTag(false);
return this;
}
public Generic<T> _pre() {
super._pre(true);
return this;
}
public Generic<T> _attr(String name, String value) {
addAttr(name, value);
return this;
}
public Generic<Generic<T>> _elem(String name, EnumSet<EOpt> opts) {
closeAttrs();
return new Generic<Generic<T>>(name, this, opts);
}
public Generic<Generic<T>> elem(String name) {
return _elem(name, of(ENDTAG));
}
@Override
public Generic<T> _(Object... lines) {
_p(true, lines);
return this;
}
@Override
public Generic<T> _r(Object... lines) {
_p(false, lines);
return this;
}
}
public HamletImpl(PrintWriter out, int nestLevel, boolean wasInline) {
this.out = out;
this.nestLevel = nestLevel;
this.wasInline = wasInline;
}
public int nestLevel() {
return nestLevel;
}
public boolean wasInline() {
return wasInline;
}
public void setWasInline(boolean state) {
wasInline = state;
}
public PrintWriter getWriter() {
return out;
}
/**
* Create a root-level generic element.
* Mostly for testing purpose.
* @param <T> type of the parent element
* @param name of the element
* @param opts {@link EOpt element options}
* @return the element
*/
public <T extends _>
Generic<T> root(String name, EnumSet<EOpt> opts) {
return new Generic<T>(name, null, opts);
}
public <T extends _> Generic<T> root(String name) {
return root(name, of(ENDTAG));
}
protected void printStartTag(String name, EnumSet<EOpt> opts) {
indent(opts);
sb.setLength(0);
out.print(sb.append('<').append(name).toString()); // for easier mock test
}
protected void indent(EnumSet<EOpt> opts) {
if (opts.contains(INLINE) && wasInline) {
return;
}
if (wasInline) {
out.println();
}
wasInline = opts.contains(INLINE) || opts.contains(PRE);
for (int i = 0; i < nestLevel; ++i) {
out.print(INDENT_CHARS);
}
++indents;
}
protected void printEndTag(String name, EnumSet<EOpt> opts) {
if (!opts.contains(ENDTAG)) {
return;
}
if (!opts.contains(PRE)) {
indent(opts);
} else {
wasInline = opts.contains(INLINE);
}
sb.setLength(0);
out.print(sb.append("</").append(name).append('>').toString()); // ditto
if (!opts.contains(INLINE)) {
out.println();
}
}
protected void printAttr(String name, String value) {
sb.setLength(0);
sb.append(' ').append(name);
if (value != null) {
sb.append("=\"").append(escapeHtml4(value)).append("\"");
}
out.print(sb.toString());
}
/**
* Sub-classes should override this to do something interesting.
* @param cls the sub-view class
*/
protected void subView(Class<? extends SubView> cls) {
indent(of(ENDTAG)); // not an inline view
sb.setLength(0);
out.print(sb.append('[').append(cls.getName()).append(']').toString());
out.println();
}
/**
* Parse selector into id and classes
* @param selector in the form of (#id)?(.class)*
* @return an two element array [id, "space-separated classes"].
* Either element could be null.
* @throws WebAppException when both are null or syntax error.
*/
public static String[] parseSelector(String selector) {
String[] result = new String[]{null, null};
Iterable<String> rs = SS.split(selector);
Iterator<String> it = rs.iterator();
if (it.hasNext()) {
String maybeId = it.next();
if (maybeId.charAt(0) == '#') {
result[S_ID] = maybeId.substring(1);
if (it.hasNext()) {
result[S_CLASS] = SJ.join(Iterables.skip(rs, 1));
}
} else {
result[S_CLASS] = SJ.join(rs);
}
return result;
}
throw new WebAppException("Error parsing selector: "+ selector);
}
/**
* Set id and/or class attributes for an element.
* @param <E> type of the element
* @param e the element
* @param selector Haml form of "(#id)?(.class)*"
* @return the element
*/
public static <E extends CoreAttrs> E setSelector(E e, String selector) {
String[] res = parseSelector(selector);
if (res[S_ID] != null) {
e.$id(res[S_ID]);
}
if (res[S_CLASS] != null) {
e.$class(res[S_CLASS]);
}
return e;
}
public static <E extends LINK> E setLinkHref(E e, String href) {
if (href.endsWith(".css")) {
e.$rel("stylesheet"); // required in html5
}
e.$href(href);
return e;
}
public static <E extends SCRIPT> E setScriptSrc(E e, String src) {
if (src.endsWith(".js")) {
e.$type("text/javascript"); // required in html4
}
e.$src(src);
return e;
}
}

View File

@ -1,27 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
* Deprecated.
* Use org.apache.hadoop.yarn.webapp.hamlet2 package instead.
*/
@Deprecated
@InterfaceAudience.LimitedPrivate({"YARN", "MapReduce"})
package org.apache.hadoop.yarn.webapp.hamlet;
import org.apache.hadoop.classification.InterfaceAudience;

View File

@ -1,57 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.yarn.webapp.hamlet;
import org.junit.Test;
import static org.junit.Assert.*;
import org.apache.hadoop.yarn.webapp.WebAppException;
import static org.apache.hadoop.yarn.webapp.hamlet.HamletImpl.*;
public class TestParseSelector {
@Test public void testNormal() {
String[] res = parseSelector("#id.class");
assertEquals("id", res[S_ID]);
assertEquals("class", res[S_CLASS]);
}
@Test public void testMultiClass() {
String[] res = parseSelector("#id.class1.class2");
assertEquals("id", res[S_ID]);
assertEquals("class1 class2", res[S_CLASS]);
}
@Test public void testMissingId() {
String[] res = parseSelector(".class");
assertNull(res[S_ID]);
assertEquals("class", res[S_CLASS]);
}
@Test public void testMissingClass() {
String[] res = parseSelector("#id");
assertEquals("id", res[S_ID]);
assertNull(res[S_CLASS]);
}
@Test(expected=WebAppException.class) public void testMissingAll() {
parseSelector("");
}
}

View File

@ -1,33 +1,31 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.yarn.webapp.hamlet;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.yarn.webapp.hamlet2;
import java.util.EnumSet;
import java.io.PrintWriter;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import org.apache.hadoop.yarn.webapp.SubView;
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
import static org.apache.hadoop.yarn.webapp.hamlet.HamletSpec.*;
import static org.apache.hadoop.yarn.webapp.hamlet2.HamletSpec.*;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
public class TestHamlet {
@ -36,11 +34,11 @@ public class TestHamlet {
title("test").
h1("heading 1").
p("#id.class").
b("hello").
em("world!")._().
b("hello").
em("world!").__().
div("#footer").
_("Brought to you by").
a("http://hostname/", "Somebody")._();
__("Brought to you by").
a("https://hostname/", "Somebody").__();
PrintWriter out = h.getWriter();
out.flush();
@ -64,7 +62,7 @@ public class TestHamlet {
verify(out).print(" id=\"footer\"");
verify(out).print("Brought to you by");
verify(out).print("<a");
verify(out).print(" href=\"http://hostname/\"");
verify(out).print(" href=\"https://hostname/\"");
verify(out).print("Somebody");
verify(out).print("</a>");
verify(out).print("</div>");
@ -79,9 +77,9 @@ public class TestHamlet {
TABLE t = h.table("#id");
for (int i = 0; i < 3; ++i) {
t.tr().td("1").td("2")._();
t.tr().td("1").td("2").__();
}
t._();
t.__();
PrintWriter out = h.getWriter();
out.flush();
@ -97,12 +95,12 @@ public class TestHamlet {
meta_http("Content-type", "text/html; charset=utf-8").
title("test enum attrs").
link().$rel("stylesheet").
$media(EnumSet.of(Media.screen, Media.print)).
$type("text/css").$href("style.css")._().
$media(EnumSet.of(Media.screen, Media.print)).
$type("text/css").$href("style.css").__().
link().$rel(EnumSet.of(LinkType.index, LinkType.start)).
$href("index.html")._();
$href("index.html").__();
h.div("#content")._("content")._();
h.div("#content").__("content").__();
PrintWriter out = h.getWriter();
out.flush();
@ -126,12 +124,12 @@ public class TestHamlet {
@Test public void testPreformatted() {
Hamlet h = newHamlet().
div().
i("inline before pre").
pre().
_("pre text1\npre text2").
i("inline in pre").
_("pre text after inline")._().
i("inline after pre")._();
i("inline before pre").
pre().
__("pre text1\npre text2").
i("inline in pre").
__("pre text after inline").__().
i("inline after pre").__();
PrintWriter out = h.getWriter();
out.flush();
@ -149,8 +147,8 @@ static class TestView2 implements SubView {
@Test public void testSubViews() {
Hamlet h = newHamlet().
title("test sub-views").
div("#view1")._(TestView1.class)._().
div("#view2")._(TestView2.class)._();
div("#view1").__(TestView1.class).__().
div("#view2").__(TestView2.class).__();
PrintWriter out = h.getWriter();
out.flush();
@ -163,4 +161,4 @@ static Hamlet newHamlet() {
PrintWriter out = spy(new PrintWriter(System.out));
return new Hamlet(out, 0, false);
}
}
}

View File

@ -1,30 +1,29 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.yarn.webapp.hamlet;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.yarn.webapp.hamlet2;
import java.io.PrintWriter;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import org.apache.hadoop.yarn.webapp.hamlet.HamletImpl;
import org.apache.hadoop.yarn.webapp.hamlet.HamletSpec.*;
import org.apache.hadoop.yarn.webapp.hamlet2.HamletSpec.*;
public class TestHamletImpl {
/**
@ -35,25 +34,25 @@ public class TestHamletImpl {
PrintWriter out = spy(new PrintWriter(System.out));
HamletImpl hi = new HamletImpl(out, 0, false);
hi.
root("start")._attr("name", "value").
_("start text").
root("start")._attr("name", "value").
__("start text").
elem("sub")._attr("name", "value").
_("sub text")._().
__("sub text").__().
elem("sub1")._noEndTag()._attr("boolean", null).
_("sub1text")._().
_("start text2").
__("sub1text").__().
__("start text2").
elem("pre")._pre().
_("pre text").
elem("i")._inline()._("inline")._()._().
elem("i")._inline()._("inline after pre")._().
_("start text3").
__("pre text").
elem("i")._inline().__("inline").__().__().
elem("i")._inline().__("inline after pre").__().
__("start text3").
elem("sub2").
_("sub2text")._().
__("sub2text").__().
elem("sub3")._noEndTag().
_("sub3text")._().
__("sub3text").__().
elem("sub4")._noEndTag().
elem("i")._inline()._("inline")._().
_("sub4text")._()._();
elem("i")._inline().__("inline").__().
__("sub4text").__().__();
out.flush();
assertEquals(0, hi.nestLevel);
@ -75,11 +74,11 @@ public class TestHamletImpl {
verify(e).$class("class");
H1 t = mock(H1.class);
HamletImpl.setSelector(t, "#id.class")._("heading");
HamletImpl.setSelector(t, "#id.class").__("heading");
verify(t).$id("id");
verify(t).$class("class");
verify(t)._("heading");
verify(t).__("heading");
}
@Test public void testSetLinkHref() {
@ -105,4 +104,4 @@ public class TestHamletImpl {
verifyNoMoreInteractions(script);
}
}
}

View File

@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.yarn.webapp.hamlet2;
import org.junit.Test;
import static org.apache.hadoop.yarn.webapp.hamlet2.HamletImpl.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.apache.hadoop.yarn.webapp.WebAppException;
public class TestParseSelector {
@Test public void testNormal() {
String[] res = parseSelector("#id.class");
assertEquals("id", res[S_ID]);
assertEquals("class", res[S_CLASS]);
}
@Test public void testMultiClass() {
String[] res = parseSelector("#id.class1.class2");
assertEquals("id", res[S_ID]);
assertEquals("class1 class2", res[S_CLASS]);
}
@Test public void testMissingId() {
String[] res = parseSelector(".class");
assertNull(res[S_ID]);
assertEquals("class", res[S_CLASS]);
}
@Test public void testMissingClass() {
String[] res = parseSelector("#id");
assertEquals("id", res[S_ID]);
assertNull(res[S_CLASS]);
}
@Test(expected=WebAppException.class) public void testMissingAll() {
parseSelector("");
}
}