/* * Copyright (c) 2016 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.net4j.util.container; import org.eclipse.net4j.util.container.IContainerDelta.Kind; import org.eclipse.net4j.util.event.EventUtil; import org.eclipse.net4j.util.event.IEvent; import org.eclipse.net4j.util.event.IListener; import org.eclipse.net4j.util.lifecycle.ILifecycle; import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; /** * @author Eike Stepper * @since 3.6 */ public class SelfAttachingContainerListener implements IListener { public SelfAttachingContainerListener() { } public void attach(Object element) { if (shouldAttach(element)) { EventUtil.addListener(element, this); if (shouldDescend(element)) { try { Object[] children = ContainerUtil.getElements(element); if (children != null) { for (Object child : children) { try { attach(child); } catch (Exception ex) { handleException(ex); } } } } catch (Exception ex) { handleException(ex); } } } } public void detach(Object element) { if (shouldAttach(element)) { if (shouldDescend(element)) { try { Object[] children = ContainerUtil.getElements(element); if (children != null) { for (Object child : children) { try { detach(child); } catch (Exception ex) { handleException(ex); } } } } catch (Exception ex) { handleException(ex); } } EventUtil.removeListener(element, this); } } public void notifyEvent(IEvent event) { if (event instanceof IContainerEvent<?>) { notifyContainerEvent((IContainerEvent<?>)event); } else { notifyOtherEvent(event); } } protected void notifyContainerEvent(IContainerEvent<?> event) { for (IContainerDelta<?> delta : event.getDeltas()) { final Object element = delta.getElement(); if (delta.getKind() == Kind.ADDED) { if (isWaitForActive() && !isActive(element)) { EventUtil.addListener(element, new LifecycleEventAdapter() { @Override protected void onActivated(ILifecycle lifecycle) { lifecycle.removeListener(this); attach(element); } }); } else { attach(element); } } else { detach(element); } } } protected void notifyOtherEvent(IEvent event) { } protected boolean shouldAttach(Object element) { return true; } protected boolean shouldDescend(Object element) { return !(element instanceof DoNotDescend); } protected boolean isWaitForActive() { return true; } protected boolean isActive(Object element) { return LifecycleUtil.isActive(element); } protected void handleException(Exception ex) { } /** * @author Eike Stepper */ public interface DoNotDescend { } /** * @author Eike Stepper */ public static class Delegating extends SelfAttachingContainerListener { private final IListener delegate; private final boolean delegateContainerEvents; public Delegating(IListener delegate, boolean delegateContainerEvents) { this.delegate = delegate; this.delegateContainerEvents = delegateContainerEvents; } public Delegating(IListener delegate) { this(delegate, false); } @Override protected void notifyContainerEvent(IContainerEvent<?> event) { super.notifyContainerEvent(event); if (delegateContainerEvents) { delegate.notifyEvent(event); } } @Override protected void notifyOtherEvent(IEvent event) { delegate.notifyEvent(event); } } }