/**
* Copyright 2010 the original author or authors.
*
* This file is part of Zksample2. http://zksample2.sourceforge.net/
*
* Zksample2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Zksample2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Zksample2. If not, see <http://www.gnu.org/licenses/gpl.html>.
*/
package de.forsthaus.util;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.zkoss.zk.ui.AbstractComponent;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.sys.ComponentsCtrl;
/**
* Helper class for showing the zkoss component tree in the console for a root
* component.
*
* <pre>
* Call it with:
* System.out.println(ZkossComponentTreeUtil.getZulTree(aComponent));
* </pre>
*
* @author bbruhns
*
*/
public class ZkossComponentTreeUtil {
final private static class FieldListener implements IAddListener {
private final Field field;
FieldListener(Field field) {
super();
this.field = field;
}
@Override
public void addListener(Component component, StringBuilder result, int depth) {
try {
final Map<?, ?> m = (Map<?, ?>) this.field.get(component);
if (m != null && !m.isEmpty()) {
for (final Map.Entry<?, ?> entry : m.entrySet()) {
result.append(StringUtils.leftPad("", depth << 2) + " " + entry.getKey() + " -> " + entry.getValue() + "\n");
}
}
} catch (final IllegalArgumentException e) {
} catch (final IllegalAccessException e) {
}
}
}
private interface IAddListener {
void addListener(Component component, StringBuilder result, int depth);
}
final private static IAddListener ADD_LISTENER;
static {
IAddListener tmp = null;
try {
final Field field;
field = AbstractComponent.class.getDeclaredField("_listeners");
field.setAccessible(true);
tmp = new FieldListener(field);
} catch (final SecurityException e) {
} catch (final NoSuchFieldException e) {
}
if (tmp == null) {
tmp = new IAddListener() {
@Override
public void addListener(Component component, StringBuilder result, int depth) {
}
};
}
ADD_LISTENER = tmp;
}
static public CharSequence getZulTree(Component component) {
return new ZkossComponentTreeUtil().getZulTreeImpl(component);
}
private ZkossComponentTreeUtil() {
super();
}
private CharSequence createCompName(Component component) {
final StringBuilder sb = new StringBuilder();
sb.append(component.getClass().getSimpleName());
final String id = component.getId();
if (StringUtils.isNotBlank(id) && !ComponentsCtrl.isAutoUuid(id)) {
sb.append(" id=\"" + id + "\"");
}
return sb;
}
private CharSequence getZulTreeImpl(Component component) {
if (component == null) {
return "Component is null!";
}
final StringBuilder result = new StringBuilder(6000);
return getZulTreeImpl(component, result, -1);
}
private StringBuilder getZulTreeImpl(Component component, StringBuilder result, int depth) {
++depth;
final CharSequence id = createCompName(component);
if (CollectionUtils.isEmpty(component.getChildren())) {
result.append(StringUtils.leftPad("", depth << 2) + "<" + id + " />\n");
return result;
}
result.append(StringUtils.leftPad("", depth << 2) + "<" + id + ">\n");
ADD_LISTENER.addListener(component, result, depth);
for (final Iterator<?> iterator = component.getChildren().iterator(); iterator.hasNext();) {
getZulTreeImpl((Component) iterator.next(), result, depth);
}
result.append(StringUtils.leftPad("", depth << 2) + "<" + component.getClass().getSimpleName() + " />\n");
return result;
}
}