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    }