/* * Copyright (c) 2011 Petter Holmström * * 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.github.peholmst.mvp4vaadin; import java.util.logging.Level; import java.util.logging.Logger; import com.github.peholmst.mvp4vaadin.events.DescriptionChangedViewEvent; import com.github.peholmst.mvp4vaadin.events.DisplayNameChangedViewEvent; import com.github.peholmst.mvp4vaadin.events.InitializedViewEvent; import com.github.peholmst.stuff4vaadin.adapter.Adaptable; import com.github.peholmst.stuff4vaadin.adapter.AdaptableSupport; import com.github.peholmst.stuff4vaadin.adapter.UnsupportedAdapterException; import com.github.peholmst.stuff4vaadin.visitor.VisitableList; import com.github.peholmst.stuff4vaadin.visitor.Visitor; /** * This class is intended to be used as a delegate by {@link View} * implementations. It includes a full implementation of the {@link View} * interface. Usage of this class requires that the owning class implements the * {@link ViewDelegateOwner} interface. * <p> * This class exists in order to make it possible to extend different base * classes when implementing the {@link View} interface without having to * implement all the basic View methods again and again and again. * * @see AbstractView * @see AbstractViewComponent * * @author Petter Holmström * @since 1.0 */ public class ViewDelegate<V extends View, P extends Presenter<V>> implements View { private static final long serialVersionUID = -8388839248083280057L; private String displayName; private String description; private final VisitableList<ViewListener> listenerList = new VisitableList<ViewListener>(); private boolean initialized = false; private transient Logger logger; private final ViewDelegateOwner<V, P> delegateOwner; private final AdaptableSupport adaptableSupport = new AdaptableSupport(); private P presenter; /** * Creates a new <code>ViewDelegate</code> of the specified delegate owner. */ public ViewDelegate(ViewDelegateOwner<V, P> delegateOwner) { this.delegateOwner = delegateOwner; } private Logger getLogger() { if (logger == null) { logger = Logger.getLogger(delegateOwner.getClass().getName()); } return logger; } @Override public String getDisplayName() { return displayName; } /** * Sets the display name of the view and fires a * {@link DisplayNameChangedViewEvent}. */ public void setDisplayName(String displayName) { final String old = this.displayName; this.displayName = displayName; fireViewEvent(new DisplayNameChangedViewEvent(delegateOwner, old, displayName)); } @Override public String getViewDescription() { return description; } /** * Sets the description of the view and fires a * {@link DescriptionChangedViewEvent}. */ public void setViewDescription(String description) { final String old = this.description; this.description = description; fireViewEvent(new DescriptionChangedViewEvent(delegateOwner, old, description)); } /** * Gets the presenter of the view. * * @return the presenter instance (never <code>null</code> once the view has * been initialized). */ public P getPresenter() { return presenter; } /** * Sets the presenter of the view. This method is useful for dependency * injection frameworks. If the view has already been initialized, this * method will throw an exception. */ public void setPresenter(P presenter) { if (isInitialized()) { throw new IllegalStateException("already initialized"); } this.presenter = presenter; } /** * {@inheritDoc} * * @see ViewDelegateOwner#createPresenter() * @see ViewDelegateOwner#initView() * @see ViewDelegateOwner#finalizeInitialization() * @see InitializedViewEvent */ @Override public void init() { if (isInitialized()) { throw new IllegalStateException("already initialized"); } if (presenter == null) { getLogger().log(Level.FINE, "Creating new presenter instance"); presenter = delegateOwner.createPresenter(); } getLogger().log(Level.FINE, "Initializing view {0}", this); delegateOwner.initView(); getLogger().log(Level.FINE, "Initializing presenter {0}", presenter); presenter.init(); getLogger().log(Level.FINE, "View and presenter initialized, finalizing initialization"); delegateOwner.finalizeInitialization(); initialized = true; fireViewEvent(new InitializedViewEvent(delegateOwner)); } @Override public boolean isInitialized() { return initialized; } /** * This method is intended to be used by unit tests only. */ void setInitialized(boolean initialized) { this.initialized = initialized; } @Override public void addListener(ViewListener listener) { if (listener != null) { listenerList.add(listener); } } @Override public void removeListener(ViewListener listener) { if (listener != null) { listenerList.remove(listener); } } @Override public void fireViewEvent(final ViewEvent event) { if (event == null) { return; } getLogger().log(Level.FINE, "Firing event {0}", event); listenerList.visitItems(new Visitor<ViewListener>() { @Override public void visit(ViewListener visitable) { visitable.handleViewEvent(event); } }); } @Override @Deprecated public String getDescription() { return getViewDescription(); } @Override public boolean supportsAdapter(Class<?> adapterClass) { return adaptableSupport.supportsAdapter(adapterClass); } @Override public <T> T adapt(Class<T> adapterClass) throws UnsupportedAdapterException { return adaptableSupport.adapt(adapterClass); } /** * Returns the <code>AdaptableSupport</code> instance used by the view * delegate to implement the {@link Adaptable} interface. */ public AdaptableSupport getAdaptableSupport() { return adaptableSupport; } }