package lt.inventi.wicket.component.breadcrumb;
import static lt.inventi.wicket.component.breadcrumb.BreadcrumbPageParameters.getOptionalTrailId;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.Session;
import org.apache.wicket.application.IComponentInitializationListener;
import org.apache.wicket.application.IComponentInstantiationListener;
import org.apache.wicket.application.IComponentOnBeforeRenderListener;
import org.apache.wicket.request.component.IRequestablePage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class BreadcrumbTrailExtendingListener implements IComponentOnBeforeRenderListener {
/**
* We cannot use {@link IComponentInitializationListener} or
* {@link IComponentInstantiationListener} because navigation to the
* breadcrumbs in the trail won't always create/initialize pages (in case
* they're stateful and still in the page store). We construct unique trail
* ids based on the page's hashCode and a deserialized page's hashCode
* doesn't have to match the hashCode of the serialized one, thus we cannot
* reliably find the previous page trail without extending it on each
* render.
* <p>
* Possible improvement: store the newly created breadcrumb in the session's
* metadata and use it in all further next page links. This way we can use
* stable breadcrumb ids (page id + page class) and avoid creating new
* breadcrumbs when the same page is rerendered (same page id + class but
* different page object and thus hashCode).
*/
private static final Logger logger = LoggerFactory.getLogger(BreadcrumbTrailExtendingListener.class);
private final IBreadcrumbPageFilter pageFilter;
private final IComponentBreadcrumbTitleProvider titleProvider;
public BreadcrumbTrailExtendingListener(IBreadcrumbPageFilter pageFilter, IComponentBreadcrumbTitleProvider titleProvider) {
this.pageFilter = pageFilter;
this.titleProvider = titleProvider;
}
@Override
public void onBeforeRender(Component component) {
if (component instanceof Page) {
if (pageFilter.shouldCreateBreadcrumbFor((IRequestablePage) component)) {
Page p = (Page) component;
Breadcrumb crumb = createBreadcrumbFrom(p);
String maybeTrailId = getOptionalTrailId(p.getPageParameters());
BreadcrumbTrailHistory.extendTrail(maybeTrailId, crumb);
if (logger.isTraceEnabled()) {
logger.trace("Extended breadcrumb trail for trail {} with crumb {}", maybeTrailId, crumb);
logger.trace("Session size after extending trail: " + Session.get().getSizeInBytes() + " bytes");
}
} else {
if (logger.isTraceEnabled()) {
logger.trace("Skipping breadcrumb trail extension for page: " + component);
}
}
}
}
private Breadcrumb createBreadcrumbFrom(Page p) {
return new Breadcrumb(p, titleProvider.getBreadcrumbTitle(p));
}
}