001 /*
002 * Copyright 2002-2004 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016 package org.springframework.richclient.application.config;
017
018 import java.util.ArrayList;
019 import java.util.Iterator;
020 import java.util.List;
021
022 import org.springframework.beans.BeansException;
023 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
024 import org.springframework.beans.factory.support.DefaultListableBeanFactory;
025 import org.springframework.context.ApplicationContext;
026 import org.springframework.context.ApplicationEvent;
027 import org.springframework.context.ApplicationListener;
028 import org.springframework.context.support.ClassPathXmlApplicationContext;
029 import org.springframework.richclient.application.Application;
030 import org.springframework.richclient.application.support.ApplicationWindowCommandManager;
031 import org.springframework.richclient.command.CommandGroup;
032
033 /**
034 * @author Keith Donald
035 */
036 public class DefaultApplicationLifecycleAdvisor extends ApplicationLifecycleAdvisor
037 implements ApplicationListener {
038 private String windowCommandManagerBeanName;
039
040 private String toolBarBeanName;
041
042 private String menuBarBeanName;
043
044 private String windowCommandBarDefinitions;
045
046 private ConfigurableListableBeanFactory openingWindowCommandBarFactory;
047
048 /** Set of child command contexts created - used to bridge application events. */
049 private ArrayList childContexts = new ArrayList();
050
051 public void setWindowCommandBarDefinitions(String commandBarDefinitionLocation) {
052 this.windowCommandBarDefinitions = commandBarDefinitionLocation;
053 }
054
055 public void setWindowCommandManagerBeanName(String commandManagerBeanName) {
056 this.windowCommandManagerBeanName = commandManagerBeanName;
057 }
058
059 public void setMenubarBeanName(String menubarBeanName) {
060 this.menuBarBeanName = menubarBeanName;
061 }
062
063 public void setToolbarBeanName(String toolbarBeanName) {
064 this.toolBarBeanName = toolbarBeanName;
065 }
066
067 public ApplicationWindowCommandManager createWindowCommandManager() {
068 initNewWindowCommandBarFactory();
069 if (windowCommandManagerBeanName == null || !getCommandBarFactory().containsBean(windowCommandManagerBeanName)) {
070 return new ApplicationWindowCommandManager();
071 }
072 return (ApplicationWindowCommandManager)getCommandBarFactory().getBean(windowCommandManagerBeanName,
073 ApplicationWindowCommandManager.class);
074 }
075
076 protected void initNewWindowCommandBarFactory() {
077 if (windowCommandBarDefinitions != null) {
078 // Install our own application context so we can register needed post-processors
079 final CommandBarApplicationContext commandBarContext =
080 new CommandBarApplicationContext(windowCommandBarDefinitions);
081 addChildCommandContext(commandBarContext);
082 this.openingWindowCommandBarFactory = commandBarContext.getBeanFactory();
083 } else {
084 this.openingWindowCommandBarFactory = new DefaultListableBeanFactory();
085 }
086 }
087
088 protected ConfigurableListableBeanFactory getCommandBarFactory() {
089 return openingWindowCommandBarFactory;
090 }
091
092 public CommandGroup getMenuBarCommandGroup() {
093 CommandGroup menuBarCommandGroup = getCommandGroup(menuBarBeanName);
094 return menuBarCommandGroup != null ? menuBarCommandGroup : super.getMenuBarCommandGroup();
095 }
096
097 public CommandGroup getToolBarCommandGroup() {
098 CommandGroup toolBarCommandGroup = getCommandGroup(toolBarBeanName);
099 return toolBarCommandGroup != null ? toolBarCommandGroup : super.getToolBarCommandGroup();
100 }
101
102 protected CommandGroup getCommandGroup(String name) {
103 if (name == null || !getCommandBarFactory().containsBean(name)) {
104 return null;
105 }
106 return (CommandGroup)getCommandBarFactory().getBean(name);
107 }
108
109 /**
110 * We need to deliver all application events down to the child command
111 * contexts that have been created.
112 * @param event to deliver
113 */
114 public void onApplicationEvent(ApplicationEvent event) {
115 // Dispatch the event to all the child command contexts
116 for( Iterator iter = getChildCommandContexts().iterator(); iter.hasNext(); ) {
117 ApplicationContext ctx = (ApplicationContext) iter.next();
118 ctx.publishEvent(event);
119 }
120 }
121
122 /**
123 * Get all the child command contexts that have been created.
124 * <p>
125 * <em>Note, theactual collection is being returned - so be careful what you
126 * do to it.</em>
127 *
128 * @return list of contexts
129 */
130 protected List getChildCommandContexts() {
131 return childContexts;
132 }
133
134 /**
135 * Add a new child command context.
136 * @param context
137 */
138 protected void addChildCommandContext( ApplicationContext context ) {
139 childContexts.add( context );
140 }
141
142 /**
143 * Simple extension to allow us to inject our special bean post-processors
144 * and control event publishing.
145 */
146 private class CommandBarApplicationContext extends ClassPathXmlApplicationContext {
147
148 /**
149 * Constructor. Load bean definitions from the specified location.
150 * @param location of bean definitions
151 */
152 public CommandBarApplicationContext(String location) {
153 super( new String[] { location }, false, Application.instance().getApplicationContext() );
154 refresh();
155 }
156
157 /**
158 * Install our bean post-processors.
159 * @param beanFactory the bean factory used by the application context
160 * @throws org.springframework.beans.BeansException in case of errors
161 */
162 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
163 beanFactory.addBeanPostProcessor( new ApplicationWindowSetter( getOpeningWindow() ) );
164 }
165
166 /**
167 * Publish an event in to this context. Since we are always getting
168 * notification from a parent context, this overriden implementation does
169 * not dispatch up to the parent context, thus avoiding an infinite loop.
170 */
171 public void publishEvent(ApplicationEvent event) {
172 // Temporarily disconnect our parent so the event publishing doesn't
173 // result in an infinite loop.
174 ApplicationContext parent = getParent();
175 setParent(null);
176 super.publishEvent(event);
177 setParent(parent);
178 }
179 }
180 }