/* * Copyright (c) 2010-2016 Evolveum * * 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.evolveum.midpoint.web.component.breadcrumbs; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import org.apache.wicket.Component; import org.apache.wicket.RestartResponseException; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.model.AbstractReadOnlyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.request.mapper.parameter.PageParameters; import java.io.Serializable; import java.util.Arrays; /** * Breadcrumb object that is stored in the session. It represents the way "back" to the main menu. * * We need to be extra careful about the memory references here. This object goes in the session. * Therefore we cannot allow models to be stored in the session. The models may have references * to (possibly big) pages and other rich objects. The references are there mostly to load the * models. But we do not want that. We want to store only the values. Therefore the model values * are copied to simple strings on model detach(). * * @author Viliam Repan (lazyman) * @author semancik */ public class Breadcrumb implements Serializable, DebugDumpable { private static final long serialVersionUID = 1L; private static final Trace LOG = TraceManager.getTrace(Breadcrumb.class); transient private IModel<String> labelModel; private String label; transient private IModel<String> iconModel; private String icon; private boolean useLink = false; private boolean visible = true; public Breadcrumb() { } public Breadcrumb(IModel<String> labelModel) { this(labelModel, null); } public Breadcrumb(IModel<String> labelModel, IModel<String> icon) { setLabel(labelModel); setIcon(icon); } public PageParameters getParameters() { return null; } public IModel<String> getLabel() { if (labelModel == null && label != null) { labelModel = new AbstractReadOnlyModel<String>() { private static final long serialVersionUID = 1L; @Override public String getObject() { return label; } }; } return labelModel; } public void setLabel(final IModel<String> label) { if (label == null) { this.labelModel = null; return; } this.labelModel = new AbstractReadOnlyModel<String>() { private static final long serialVersionUID = 1L; @Override public String getObject() { try { return label.getObject(); } catch (Exception ex) { LOG.warn("Couldn't load breadcrumb model value", ex); return null; } } @Override public void detach() { super.detach(); Breadcrumb.this.label = label.getObject(); Breadcrumb.this.labelModel = null; } }; } public IModel<String> getIcon() { if (iconModel == null && icon != null) { iconModel = new AbstractReadOnlyModel<String>() { private static final long serialVersionUID = 1L; @Override public String getObject() { return icon; } }; } return iconModel; } public void setIcon(final IModel<String> icon) { if (icon == null) { this.iconModel = null; return; } this.iconModel = new AbstractReadOnlyModel<String>() { private static final long serialVersionUID = 1L; @Override public String getObject() { try { return icon.getObject(); } catch (Exception ex) { LOG.warn("Couldn't load breadcrumb model value", ex); return null; } } @Override public void detach() { super.detach(); Breadcrumb.this.icon = icon.getObject(); Breadcrumb.this.iconModel = null; } }; } public boolean isUseLink() { return useLink; } public void setUseLink(boolean useLink) { this.useLink = useLink; } public boolean isVisible() { return visible; } public void setVisible(boolean visible) { this.visible = visible; } public WebPage redirect() { throw new UnsupportedOperationException("Should be implemented in a subclass"); } public RestartResponseException getRestartResponseException() { throw new UnsupportedOperationException("Should be implemented in a subclass"); } private <T extends Serializable> IModel<T> wrapModel(final IModel<T> model) { if (model == null) { return null; } return new AbstractReadOnlyModel<T>() { @Override public T getObject() { try { return model.getObject(); } catch (Exception ex) { LOG.warn("Couldn't load breadcrumb model value", ex); return null; } } @Override public void detach() { super.detach(); model.getObject(); } }; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; //we don't compare label/icon models, we would need to compare models values return true; } @Override public int hashCode() { return Arrays.hashCode(new Object[]{labelModel, iconModel}); } @Override public String debugDump() { return debugDump(0); } @Override public String debugDump(int indent) { StringBuilder sb = new StringBuilder(); DebugUtil.indentDebugDump(sb, indent); sb.append(this.getClass().getSimpleName()); sb.append("\n"); DebugUtil.debugDumpWithLabelLn(sb, "labelModel", labelModel==null?"":labelModel.toString(), indent+1); DebugUtil.debugDumpWithLabelLn(sb, "label", label, indent+1); DebugUtil.debugDumpWithLabelLn(sb, "iconModel", iconModel==null?"":iconModel.toString(), indent+1); DebugUtil.debugDumpWithLabelLn(sb, "icon", icon, indent+1); DebugUtil.debugDumpWithLabelLn(sb, "useLink", useLink, indent+1); DebugUtil.debugDumpWithLabel(sb, "visible", visible, indent+1); extendsDebugDump(sb, indent); return sb.toString(); } protected void extendsDebugDump(StringBuilder sb, int indent) { } }