/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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.alibaba.citrus.dev.handler.component;
import static com.alibaba.citrus.dev.handler.util.DomUtil.*;
import static com.alibaba.citrus.util.StringEscapeUtil.*;
import static com.alibaba.citrus.util.StringUtil.*;
import java.io.PrintWriter;
import java.util.Iterator;
import com.alibaba.citrus.dev.handler.util.AnchorValue;
import com.alibaba.citrus.dev.handler.util.Attribute;
import com.alibaba.citrus.dev.handler.util.ClassValue;
import com.alibaba.citrus.dev.handler.util.Element;
import com.alibaba.citrus.dev.handler.util.RawValue;
import com.alibaba.citrus.dev.handler.util.RefValue;
import com.alibaba.citrus.dev.handler.util.StyledValue;
import com.alibaba.citrus.dev.handler.util.TextValue;
import com.alibaba.citrus.util.ClassUtil;
import com.alibaba.citrus.util.internal.webpagelite.PageComponent;
import com.alibaba.citrus.util.internal.webpagelite.PageComponentRegistry;
import com.alibaba.citrus.util.templatelite.FallbackTextWriter;
import com.alibaba.citrus.util.templatelite.Template;
import com.alibaba.citrus.webx.handler.RequestHandlerContext;
import com.alibaba.citrus.webx.handler.support.AbstractVisitor;
public class DomComponent extends PageComponent {
public DomComponent(PageComponentRegistry registry, String componentPath) {
super(registry, componentPath);
}
public void visitTemplate(RequestHandlerContext context, Iterable<Element> elements) {
visitTemplate(context, elements, null);
}
public void visitTemplate(RequestHandlerContext context, Iterable<Element> elements,
ControlBarCallback controlBarCallback) {
getTemplate().accept(new ElementsVisitor(context, elements, controlBarCallback));
}
public interface ControlBarCallback {
void renderControlBar();
}
@SuppressWarnings("unused")
private class ElementsVisitor extends AbstractVisitor {
private final Iterable<Element> elements;
private final ControlBarCallback controlBarCallback;
private Element element;
private Attribute attr;
public ElementsVisitor(RequestHandlerContext context, Iterable<Element> elements,
ControlBarCallback controlBarCallback) {
super(context, DomComponent.this);
this.elements = elements;
this.controlBarCallback = controlBarCallback;
}
public void visitControlBar(Template controlBarTemplate) {
if (controlBarCallback == null) {
controlBarTemplate.accept(this);
} else {
controlBarCallback.renderControlBar();
}
}
public void visitElementList(Template orderedTemplate, Template unorderedTemplate) {
Iterator<Element> i = elements.iterator();
if (i.hasNext() && i.next() != null && i.hasNext()) {
orderedTemplate.accept(this); // 如果有多个elements,则显示ol
} else {
unorderedTemplate.accept(this); // 否则显示ul
}
}
public void visitElements(Template elementWithSubElementsTemplate, Template elementSelfClosedTemplate,
Template elementWithTextTemplate) {
for (Element element : elements) {
this.element = element;
if (element.hasSubElements()) {
elementWithSubElementsTemplate.accept(this);
} else if (element.getText() != null) {
elementWithTextTemplate.accept(this);
} else {
elementSelfClosedTemplate.accept(this);
}
}
}
public void visitSubElements(Template elementWithSubElementsTemplate, Template elementSelfClosedTemplate,
Template elementWithTextTemplate) {
new ElementsVisitor(context, element.subElements(), controlBarCallback).visitElements(
elementWithSubElementsTemplate, elementSelfClosedTemplate, elementWithTextTemplate);
}
public void visitElementId() {
out().print(escapeHtml(element.getId()));
}
public void visitElementPrefix(Template prefixTemplate) {
if (element.getPrefix() != null) {
prefixTemplate.accept(this);
}
}
public void visitElementPrefix() {
out().print(escapeHtml(element.getPrefix()));
}
public void visitElementNs(Template nsTemplate) {
if (element.getNs() != null) {
nsTemplate.accept(this);
}
}
public void visitElementNs() {
out().print(escapeHtml(element.getNs()));
}
public void visitElementName() {
out().print(escapeHtml(element.getLocalName()));
}
public void visitAttribute(Template attributeTemplate) {
for (Attribute attr : element.attributes()) {
this.attr = attr;
attributeTemplate.accept(this);
}
}
public void visitAttributeKey() {
out().print(escapeHtml(attr.getKey()));
}
public void visitAttributeValue(Template[] styledTextTemplates) {
new StyledValueVisitor(attr.getValue(), out()).visitStyledValue(styledTextTemplates);
}
public void visitElementTexts(Template singleLineTemplate, Template multiLineTemplate) {
if (element.getText().hasControlChars()) {
multiLineTemplate.accept(this);
} else {
singleLineTemplate.accept(this);
}
}
public void visitElementText(Template[] styledTextTemplates) {
new StyledValueVisitor(element.getText(), out()).visitStyledValue(styledTextTemplates);
}
}
@SuppressWarnings("unused")
private class StyledValueVisitor extends FallbackTextWriter<PrintWriter> {
private final StyledValue value;
private boolean withSep;
public StyledValueVisitor(StyledValue value, PrintWriter out) {
super(out);
this.value = value;
}
private void visitStyledValue(Template[] styledTextTemplates) {
Template template;
// 纯文本
if (value instanceof TextValue) {
template = styledTextTemplates[0];
context().put("value", value.getText());
template.accept(this);
}
// raw data
else if (value instanceof RawValue) {
template = styledTextTemplates[1];
context().put("packageName", ((RawValue) value).getRawType().getPackage().getName());
context().put("className", ClassUtil.getSimpleClassName(((RawValue) value).getRawType()));
context().put("value", ((RawValue) value).getRawToString());
template.accept(this);
}
// class name
else if (value instanceof ClassValue) {
template = styledTextTemplates[2];
context().put("packageName", ((ClassValue) value).getPackageName());
context().put("className", ((ClassValue) value).getSimpleName());
template.accept(this);
}
// anchor
else if (value instanceof AnchorValue) {
template = styledTextTemplates[3];
int i = 0;
for (String name : ((AnchorValue) value).getNames()) {
context().put("anchorName", toId(name));
context().put("anchorNameDisplay", name);
this.withSep = i++ > 0;
template.accept(this);
}
}
// ref to anchor
else if (value instanceof RefValue) {
template = styledTextTemplates[4];
int i = 0;
for (String name : ((RefValue) value).getNames()) {
context().put("refName", toId(name));
context().put("refNameDisplay", name);
this.withSep = i++ > 0;
template.accept(this);
}
}
// unknown value
else {
out().print("unknown value: " + value);
}
}
public void visitSep(Template sepTemplate) {
if (withSep) {
sepTemplate.accept(this);
}
}
public void visitPackageName() {
String packageName = (String) context().get("packageName");
if (!isEmpty(packageName)) {
if (!packageName.endsWith(".")) {
packageName += ".";
}
}
out().print(packageName);
}
}
}