package lt.inventi.wicket.application; import java.util.ArrayList; import java.util.List; import org.apache.wicket.Component; import org.apache.wicket.MetaDataKey; import org.apache.wicket.application.IComponentInitializationListener; import org.apache.wicket.markup.html.WebComponent; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.border.Border; import org.apache.wicket.markup.repeater.AbstractRepeater; import org.apache.wicket.markup.resolver.IComponentResolver; import org.apache.wicket.request.cycle.RequestCycle; /** * Generates permanent IDs for wicket components. */ public class StaticIdInitializationListener implements IComponentInitializationListener { private static final MetaDataKey<List<String>> ID_CACHE = new MetaDataKey<List<String>>() {}; private static final String SEPARATOR = "_"; @Override public void onInitialize(Component component) { if(needMarkupId(component)){ component.setOutputMarkupId(true); component.setMarkupId(getMarkupId(component)); } } private static String getMarkupId(Component component) { if(component instanceof WebPage){ getCache().clear(); } String id = null; if (isInRepeater(component)) { id = getRepeatersComponentId(component); } else { List<String> idCache = getCache(); id = component.getId(); Component parent = component; while (idCache.contains(id)) { parent = parent.getParent(); id = parent.getId() + SEPARATOR + id; } idCache.add(id); } //there might be situation that ID contains dots. id = id.replace(".", SEPARATOR); return id; } private static List<String> getCache() { List<String> idCache = RequestCycle.get().getMetaData(ID_CACHE); if(idCache == null){ idCache = new ArrayList<String>(); RequestCycle.get().setMetaData(ID_CACHE, idCache); } return idCache; } private static String getRepeatersComponentId(final Component component) { Component parent = component; Component lastRepeater = null; while (!(parent instanceof WebPage)) { if (parent instanceof AbstractRepeater) { lastRepeater = parent; } parent = parent.getParent(); } String id = component.getId(); if (lastRepeater == null) { return id; } parent = component; while (!(parent == lastRepeater)) { parent = parent.getParent(); id = parent.getId() + SEPARATOR + id; } return id; } private static boolean isInRepeater(Component component) { Component parent = component.findParent(AbstractRepeater.class); return parent != null; } private static boolean needMarkupId(Component component) { if(component instanceof IComponentResolver && !(component instanceof Border)){ return false; } if(component instanceof WebComponent && !(component instanceof Label)){ return false; } return true; } }