/*
* ******************************************************************************
* * Copyright 2015 See AUTHORS file.
* *
* * 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.puremvc.patterns.facade;
import com.puremvc.core.CoreController;
import com.puremvc.core.CoreModel;
import com.puremvc.core.CoreView;
import com.puremvc.patterns.command.Command;
import com.puremvc.patterns.mediator.Mediator;
import com.puremvc.patterns.observer.BaseNotification;
import com.puremvc.patterns.observer.Notification;
import com.puremvc.patterns.proxy.Proxy;
/**
* A base Singleton <code>Facade</code> implementation.
*
* @see CoreModel Model
* @see CoreView View
* @see CoreController Controller
*/
public class SimpleFacade implements Facade {
/**
* The Singleton instance of the Facade
*/
protected static SimpleFacade instance = null;
/**
* Reference to the Controller
*/
protected CoreController controller = null;
/**
* Reference to the Model
*/
protected CoreModel model = null;
/**
* Reference to the View
*/
protected CoreView view = null;
/**
* Constructor.
* <p>
* <p>
* This <code>IFacade</code> implementation is a Singleton, so you should
* not call the constructor directly, but instead call the static Singleton
* Factory method <code>Facade.getInstance()</code>
*/
protected SimpleFacade() {
initializeFacade();
}
/**
* Facade Singleton Factory method
*
* @return The Singleton instance of the Facade
*/
public synchronized static SimpleFacade getInstance() {
if (instance == null) {
instance = new SimpleFacade();
}
return instance;
}
/**
* Initialize the Multiton <code>Facade</code> instance.
* <p>
* <p>
* Called automatically by the constructor. Override in your
* subclass to do any subclass specific initializations. Be
* sure to call <code>super.initializeFacade()</code>, though.</P>
*/
protected void initializeFacade() {
initializeModel();
initializeController();
initializeView();
}
/**
* Initialize the <code>Controller</code>.
* <p>
* <p>
* Called by the <code>initializeFacade</code> method. Override this
* method in your subclass of <code>Facade</code> if one or both of the
* following are true:
* <UL>
* <LI> You wish to initialize a different <code>IController</code>.</LI>
* <LI> You have <code>Commands</code> to register with the
* <code>Controller</code> at startup.</code>. </LI>
* </UL>
* If you don't want to initialize a different <code>IController</code>,
* call <code>super.initializeController()</code> at the beginning of your
* method, then register <code>Command</code>s.
* </P>
*/
protected void initializeController() {
if (controller != null) {
return;
}
controller = CoreController.getInstance();
}
/**
* Initialize the <code>Model</code>.
* <p>
* <p>
* Called by the <code>initializeFacade</code> method. Override this
* method in your subclass of <code>Facade</code> if one or both of the
* following are true:
* <UL>
* <LI> You wish to initialize a different <code>IModel</code>.</LI>
* <LI> You have <code>Proxy</code>s to register with the Model that do
* not retrieve a reference to the Facade at construction time.</code></LI>
* </UL>
* If you don't want to initialize a different <code>IModel</code>, call
* <code>super.initializeModel()</code> at the beginning of your method,
* then register <code>Proxy</code>s.
* <p>
* Note: This method is <i>rarely</i> overridden; in practice you are more
* likely to use a <code>Command</code> to create and register <code>Proxy</code>s
* with the <code>Model</code>, since <code>Proxy</code>s with mutable
* tools will likely need to send <code>INotification</code>s and thus
* will likely want to fetch a reference to the <code>Facade</code> during
* their construction.
* </P>
*/
protected void initializeModel() {
if (model != null) {
return;
}
model = CoreModel.getInstance();
}
/**
* Initialize the <code>View</code>.
* <p>
* <p>
* Called by the <code>initializeFacade</code> method. Override this
* method in your subclass of <code>Facade</code> if one or both of the
* following are true:
* <UL>
* <LI> You wish to initialize a different <code>IView</code>.</LI>
* <LI> You have <code>Observers</code> to register with the
* <code>View</code></LI>
* </UL>
* If you don't want to initialize a different <code>IView</code>, call
* <code>super.initializeView()</code> at the beginning of your method,
* then register <code>IMediator</code> instances.
* <p>
* Note: This method is <i>rarely</i> overridden; in practice you are more
* likely to use a <code>Command</code> to create and register
* <code>Mediator</code>s with the <code>View</code>, since
* <code>IMediator</code> instances will need to send
* <code>INotification</code>s and thus will likely want to fetch a
* reference to the <code>Facade</code> during their construction.
* </P>
*/
protected void initializeView() {
if (view != null) {
return;
}
view = CoreView.getInstance();
}
/**
* Register an <code>ICommand</code> with the <code>Controller</code> by
* Notification name.
*
* @param noteName the name of the <code>INotification</code> to associate the
* <code>ICommand</code> with
* @param command an instance of the <code>ICommand</code>
*/
public void registerCommand(String noteName, Class<? extends Command> command) {
controller.registerCommand(noteName, command);
}
/**
* Remove a previously registered <code>ICommand</code> to <code>INotification</code> mapping from the Controller.
*
* @param notificationName the name of the <code>INotification</code> to remove the <code>ICommand</code> mapping for
*/
public void removeCommand(String notificationName) {
controller.removeCommand(notificationName);
}
/**
* Check if a Command is registered for a given Notification
*
* @param notificationName
* @return whether a Command is currently registered for the given <code>notificationName</code>.
*/
public boolean hasCommand(String notificationName) {
return controller.hasCommand(notificationName);
}
/**
* Register a <code>IMediator</code> with the <code>View</code>.
*
* @param mediator the name to associate with this <code>IMediator</code>
*/
public void registerMediator(Mediator mediator) {
if (view != null) {
view.registerMediator(mediator);
}
}
/**
* Register an <code>IProxy</code> with the <code>Model</code> by name.
*
* @param proxy the name of the <code>IProxy</code> instance to be
* registered with the <code>Model</code>.
*/
public void registerProxy(Proxy proxy) {
model.registerProxy(proxy);
}
/**
* Remove an <code>IMediator</code> from the <code>View</code>.
*
* @param mediatorName name of the <code>IMediator</code> to be removed.
* @return the <code>IMediator</code> that was removed from the <code>View</code>
*/
public Mediator removeMediator(String mediatorName) {
if (this.view != null) {
return this.view.removeMediator(mediatorName);
}
return null;
}
/**
* Remove an <code>IProxy</code> from the <code>Model</code> by name.
*
* @param proxyName the <code>IProxy</code> to remove from the
* <code>Model</code>.
* @return the <code>IProxy</code> that was removed from the <code>Model</code>
*/
public Proxy removeProxy(String proxyName) {
if (model != null) {
return model.removeProxy(proxyName);
}
return null;
}
/**
* Check if a Proxy is registered
*
* @param proxyName
* @return whether a Proxy is currently registered with the given <code>proxyName</code>.
*/
public boolean hasProxy(String proxyName) {
return model.hasProxy(proxyName);
}
/**
* Check if a Mediator is registered or not
*
* @param mediatorName
* @return whether a Mediator is registered with the given <code>mediatorName</code>.
*/
public boolean hasMediator(String mediatorName) {
return view.hasMediator(mediatorName);
}
/**
* Retrieve an <code>IMediator</code> from the <code>View</code>.
*
* @param mediatorName
* @return the <code>IMediator</code> previously registered with the given
* <code>mediatorName</code>.
*/
public <T extends Mediator> T retrieveMediator(String mediatorName) {
return this.view.retrieveMediator(mediatorName);
}
/**
* Retrieve an <code>IProxy</code> from the <code>Model</code> by name.
*
* @param proxyName the name of the proxy to be retrieved.
* @return the <code>IProxy</code> instance previously registered with the
* given <code>proxyName</code>.
*/
@Override
public <T extends Proxy> T retrieveProxy(String proxyName) {
return this.model.retrieveProxy(proxyName);
}
/**
* Create and send an <code>INotification</code>.
* <p>
* <p>
* Keeps us from having to construct new notification
* instances in our implementation code.
*
* @param notificationName the name of the notification to send
* @param body the body of the notification (optional)
* @param type the type of the notification (optional)
*/
public void sendNotification(String notificationName, Object body, String type) {
notifyObservers(new BaseNotification(notificationName, body, type));
}
/**
* Create and send an <code>INotification</code>.
* <p>
* <p>
* Keeps us from having to construct new notification
* instances in our implementation code.
*
* @param notificationName the name of the notification to send
* @param body the body of the notification (optional)
*/
public void sendNotification(String notificationName, Object body) {
sendNotification(notificationName, body, null);
}
/**
* Create and send an <code>INotification</code>.
* <p>
* <p>
* Keeps us from having to construct new notification
* instances in our implementation code.
*
* @param notificationName the name of the notification to send
*/
public void sendNotification(String notificationName) {
sendNotification(notificationName, null, null);
}
/**
* Notify <code>Observer</code>s of an <code>INotification</code>.
*
* @param note the <code>INotification</code> to have the <code>View</code>
* notify observers of.
*/
public void notifyObservers(Notification note) {
if (view != null) {
view.notifyObservers(note);
}
}
}