001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017/**
018 * 
019 */
020package org.apache.wicket.extensions.breadcrumb.panel;
021
022import org.apache.wicket.Component;
023import org.apache.wicket.MarkupContainer;
024import org.apache.wicket.extensions.breadcrumb.IBreadCrumbParticipant;
025import org.apache.wicket.markup.html.panel.Panel;
026import org.apache.wicket.util.visit.IVisit;
027import org.apache.wicket.util.visit.IVisitor;
028
029/**
030 * Base implementation for {@link Panel}/ {@link Component} based {@link IBreadCrumbParticipant}
031 * that decouples the implementation from the actual panel class.
032 * 
033 * @author eelcohillenius
034 */
035public abstract class BreadCrumbParticipantDelegate implements IBreadCrumbParticipant
036{
037        private static final long serialVersionUID = 1L;
038
039        private final Component component;
040
041        /**
042         * Construct.
043         * 
044         * @param component
045         */
046        public BreadCrumbParticipantDelegate(final Component component)
047        {
048                if (component == null)
049                {
050                        throw new IllegalArgumentException("component must be not null");
051                }
052                this.component = component;
053        }
054
055        /**
056         * @see org.apache.wicket.extensions.breadcrumb.IBreadCrumbParticipant#getComponent()
057         */
058        @Override
059        public Component getComponent()
060        {
061                return component;
062        }
063
064        /**
065         * If the previous participant is not null (and a component, which it should be), replace that
066         * component on it's parent with this one.
067         * 
068         * @see org.apache.wicket.extensions.breadcrumb.IBreadCrumbParticipant#onActivate(org.apache.wicket.extensions.breadcrumb.IBreadCrumbParticipant)
069         */
070        @Override
071        public void onActivate(final IBreadCrumbParticipant previous)
072        {
073                if (previous != null)
074                {
075                        MarkupContainer parent = previous.getComponent().getParent();
076                        if (parent != null)
077                        {
078                                final String thisId = component.getId();
079                                if (parent.get(thisId) != null)
080                                {
081                                        parent.replace(component);
082                                }
083                                else
084                                {
085                                        // try to search downwards to match the id
086                                        // NOTE unfortunately, we can't rely on the path pre 2.0
087                                        Component c = parent.visitChildren(new IVisitor<Component, Component>()
088                                        {
089                                                @Override
090                                                public void component(final Component component,
091                                                        final IVisit<Component> visit)
092                                                {
093                                                        if (component.getId().equals(thisId))
094                                                        {
095                                                                visit.stop(component);
096                                                        }
097                                                }
098                                        });
099                                        if (c == null)
100                                        {
101                                                // not found... do a reverse search (upwards)
102                                                c = parent.visitParents(MarkupContainer.class,
103                                                        new IVisitor<MarkupContainer, Component>()
104                                                        {
105                                                                @Override
106                                                                public void component(final MarkupContainer component,
107                                                                        final IVisit<Component> visit)
108                                                                {
109                                                                        if (component.getId().equals(thisId))
110                                                                        {
111                                                                                visit.stop(component);
112                                                                        }
113                                                                }
114                                                        });
115                                        }
116
117                                        // replace if found
118                                        if (c != null)
119                                        {
120                                                c.replaceWith(component);
121                                        }
122                                }
123                        }
124                }
125                else if (component.getParent() != null)
126                {
127                        component.getParent().replace(component);
128                }
129        }
130}