001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *                               ***
008 *
009 *   Community License: GPL 3.0
010 *
011 *   This file is free software: you can redistribute it and/or modify
012 *   it under the terms of the GNU General Public License as published
013 *   by the Free Software Foundation, either version 3 of the License,
014 *   or (at your option) any later version.
015 *
016 *   This file is distributed in the hope that it will be useful, but
017 *   WITHOUT ANY WARRANTY; without even the implied warranty of
018 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
019 *   GNU General Public License for more details.
020 *
021 *   You should have received a copy of the GNU General Public License
022 *   along with this program. If not, see <http://www.gnu.org/licenses/>.
023 *
024 *                               ***
025 *
026 *   Available Commercial License: GraniteDS SLA 1.0
027 *
028 *   This is the appropriate option if you are creating proprietary
029 *   applications and you are not prepared to distribute and share the
030 *   source code of your application under the GPL v3 license.
031 *
032 *   Please visit http://www.granitedataservices.com/license for more
033 *   details.
034 */
035package org.granite.client.tide.spring;
036
037import java.util.Map.Entry;
038
039import org.granite.client.tide.ContextAware;
040import org.granite.client.tide.EventBus;
041import org.granite.client.tide.NameAware;
042import org.granite.client.tide.Application;
043import org.granite.client.tide.ApplicationConfigurable;
044import org.granite.client.tide.data.Conflicts;
045import org.granite.client.tide.data.DataConflictListener;
046import org.granite.client.tide.data.EntityManager;
047import org.granite.client.tide.data.EntityManager.UpdateKind;
048import org.granite.client.tide.impl.SimpleContextManager;
049import org.springframework.beans.BeansException;
050import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
051import org.springframework.beans.factory.config.BeanPostProcessor;
052import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
053import org.springframework.context.ApplicationContext;
054import org.springframework.context.ApplicationContextAware;
055
056/**
057 * @author William DRAI
058 */
059public class SpringContextManager extends SimpleContextManager implements ApplicationContextAware, BeanPostProcessor, BeanFactoryPostProcessor {
060        
061        private ApplicationContext applicationContext;
062        
063        public SpringContextManager(Application application) {
064                super(application, new SpringEventBus());
065        }
066
067        public SpringContextManager(Application application, EventBus eventBus) {
068                super(application, eventBus);
069        }
070        
071        @Override
072        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
073                this.applicationContext = applicationContext;
074                setInstanceStoreFactory(new SpringInstanceStoreFactory(applicationContext));
075        if (eventBus instanceof SpringEventBus)
076            ((SpringEventBus)eventBus).setApplicationContext(applicationContext);
077        }
078        
079        @Override
080        public Object postProcessBeforeInitialization(Object instance, String name) throws BeansException {
081        if (name != null && instance instanceof NameAware)
082                ((NameAware)instance).setName(name);
083        if (instance instanceof ContextAware)
084                ((ContextAware)instance).setContext(getContext());
085        if (instance.getClass().isAnnotationPresent(ApplicationConfigurable.class))
086                application.configure(instance);
087        return instance;
088        }
089        
090        @Override
091        public Object postProcessAfterInitialization(Object instance, String name) throws BeansException {
092                return instance;
093        }
094        
095        @Override
096        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
097                beanFactory.registerSingleton("context", getContext());
098                EntityManager entityManager = getContext().getEntityManager();
099                entityManager.addListener(new SpringDataConflictListener());
100                beanFactory.registerSingleton("entityManager", entityManager);
101        beanFactory.registerSingleton("eventBus", eventBus);
102                beanFactory.registerSingleton("dataManager", getContext().getDataManager());
103                for (Entry<String, Object> entry : getContext().getInitialBeans().entrySet())
104                    beanFactory.registerSingleton(entry.getKey(), entry.getValue());
105                beanFactory.registerScope("view", new ViewScope());
106        }
107
108
109    private final class SpringDataConflictListener implements DataConflictListener {
110                @Override
111                public void onConflict(EntityManager entityManager, Conflicts conflicts) {
112                        TideApplicationEvent event = new TideApplicationEvent(getContext(null), UpdateKind.CONFLICT.eventName(), conflicts);
113                        applicationContext.publishEvent(event);
114                }
115        }
116}