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.cdi;
036
037import java.lang.annotation.Annotation;
038
039import javax.enterprise.context.ContextNotActiveException;
040import javax.enterprise.context.spi.Context;
041import javax.enterprise.context.spi.Contextual;
042import javax.enterprise.context.spi.CreationalContext;
043
044import org.granite.client.tide.ViewScope;
045import org.granite.client.tide.ViewScope.BeanResetter;
046import org.granite.client.tide.ViewScopeHolder;
047
048/**
049 * @author William DRAI
050 */
051public class ViewContext implements Context {
052        
053        // private static final Logger log = Logger.getLogger(ViewScope.class);
054        
055        private ViewScope beanCache;
056        
057        public ViewContext() {
058        }
059        
060        private ViewScope getBeanCache() {
061                if (beanCache == null) {
062                        beanCache = ViewScopeHolder.get();
063                        if (beanCache == null)
064                                throw new RuntimeException("View bean cache not set");
065                }
066                return beanCache;
067        }
068        
069        @Override
070        public <T> T get(Contextual<T> bean) {
071                return get(bean, null);
072        }
073
074        @Override
075        public <T> T get(Contextual<T> bean, CreationalContext<T> cc) {
076                if (!isActive())
077                        throw new ContextNotActiveException();
078                
079                if (bean == null)
080                        throw new IllegalArgumentException("bean cannot be null");
081                
082                String id = buildId(bean);
083                @SuppressWarnings("unchecked")
084                T instance = (T)getBeanCache().get(id);
085                if (instance != null)
086                        return instance;
087                
088                if (cc == null)
089                        return null;
090                
091                instance = bean.create(cc);
092                getBeanCache().put(id, instance);
093                getBeanCache().addResetter(id, new ViewBeanResetter<T>(bean, cc));
094                
095                return instance;
096        }
097        
098        private <T> String buildId(Contextual<T> contextual) {
099                return contextual.getClass().getName() + "#" + contextual.hashCode();
100        }
101        
102        @Override
103        public Class<? extends Annotation> getScope() {
104                return ViewScoped.class;
105        }
106        
107        @Override
108        public boolean isActive() {
109                return getBeanCache() != null;
110        }
111        
112        public static class ViewBeanResetter<T> implements BeanResetter {
113                
114                private final Contextual<T> bean;
115                private final CreationalContext<T> cc;
116                
117                public ViewBeanResetter(Contextual<T> bean, CreationalContext<T> cc) {
118                        this.bean = bean;
119                        this.cc = cc;
120                }
121                
122                @SuppressWarnings("unchecked")
123                public void reset(Object instance) {
124                        bean.destroy((T)instance, cc);
125                }
126                
127        }
128        
129}
130