/* * 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 com.github.peholmst.stuff4vaadin.adapter.Adaptable; import com.github.peholmst.stuff4vaadin.adapter.AdaptableSupport; import com.github.peholmst.stuff4vaadin.adapter.UnsupportedAdapterException; /** * This is an abstract base class for Presenters in the Model-View-Presenter * (MVP) pattern. It has been designed to work together with views that extend * the {@link AbstractView} or {@link AbstractViewComponent} base class. * <p> * The presenter contains the logic that controls the GUI. It reads information * from the Model and passes it to to the View for showing. It also receives * events from the View and decides what to do with them. * <p> * Normally, the presenter should not contain any code that couples it to a * particular View framework, such as Vaadin, JSP or Swing. There are two major * advantages with this approach: * <ol> * <li>It makes it possible to write unit tests for the GUI logic that do not * need to simulate user input.</li> * <li>It makes it easy (well, easier to be completely honest) to rewrite the * GUI using another framework, as only the views need to be reimplemented (in a * perfect world, that is).</li> * </ol> * * @see AbstractView * @see AbstractViewComponent * @author Petter Holmström * @since 1.0 * @param <V> * the type of the View that uses the Presenter. */ public abstract class Presenter<V extends View> implements Adaptable { private static final long serialVersionUID = -7842839205919502161L; private V view; private final AdaptableSupport adaptableSupport = new AdaptableSupport(); /** * Creates a new <code>Presenter</code> for the specified view. Any * initialization code should go in the {@link #init()} method. When this * constructor is invoked, the view might not yet have been initialized. * * @see AbstractView#createPresenter() * * @param view * the view that uses the presenter (must not be * <code>null</code>). */ public Presenter(V view) { if (view == null) { throw new IllegalArgumentException("null view"); } this.view = view; } /** * Creates a new <code>Presenter</code> without a view. A view must be * specified using the {@link #setView(View)} method. */ public Presenter() { } /** * Sets the view for this presenter. * * @param view * the view to set. */ public void setView(V view) { this.view = view; } /** * Gets the view that uses this presenter. If no view has been set, an * exception is thrown. * * @return the view instance (never <code>null</code>). */ public V getView() { if (view == null) { throw new IllegalStateException("View has not been set yet"); } return view; } /** * Convenience method that delegates to * {@link View#fireViewEvent(ViewEvent)}. * * @param event * the event to fire. */ public void fireViewEvent(ViewEvent event) { getView().fireViewEvent(event); } /** * This method is called to initialize the presenter. When this happens, the * view will already be initialized, i.e. invoking any methods on the view * will not throw any exceptions. * <p> * This implementation does nothing, subclasses may override. */ public void init() { // NOP } @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 presenter. */ protected AdaptableSupport getAdaptableSupport() { return adaptableSupport; } }