001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2012 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.client.tide.cdi;
022    
023    import java.lang.annotation.Annotation;
024    
025    import javax.enterprise.context.ContextNotActiveException;
026    import javax.enterprise.context.spi.Context;
027    import javax.enterprise.context.spi.Contextual;
028    import javax.enterprise.context.spi.CreationalContext;
029    
030    import org.granite.client.tide.ViewScope;
031    import org.granite.client.tide.ViewScope.BeanResetter;
032    import org.granite.client.tide.ViewScopeHolder;
033    
034    /**
035     * @author William DRAI
036     */
037    public class ViewContext implements Context {
038            
039            // private static final Logger log = Logger.getLogger(ViewScope.class);
040            
041            private ViewScope beanCache;
042            
043            public ViewContext() {
044            }
045            
046            private ViewScope getBeanCache() {
047                    if (beanCache == null) {
048                            beanCache = ViewScopeHolder.get();
049                            if (beanCache == null)
050                                    throw new RuntimeException("View bean cache not set");
051                    }
052                    return beanCache;
053            }
054            
055            @Override
056            public <T> T get(Contextual<T> bean) {
057                    return get(bean, null);
058            }
059    
060            @Override
061            public <T> T get(Contextual<T> bean, CreationalContext<T> cc) {
062                    if (!isActive())
063                            throw new ContextNotActiveException();
064                    
065                    if (bean == null)
066                            throw new IllegalArgumentException("bean cannot be null");
067                    
068                    String id = buildId(bean);
069                    @SuppressWarnings("unchecked")
070                    T instance = (T)getBeanCache().get(id);
071                    if (instance != null)
072                            return instance;
073                    
074                    if (cc == null)
075                            return null;
076                    
077                    instance = bean.create(cc);
078                    getBeanCache().put(id, instance);
079                    getBeanCache().addResetter(id, new ViewBeanResetter<T>(bean, cc));
080                    
081                    return instance;
082            }
083            
084            private <T> String buildId(Contextual<T> contextual) {
085                    return contextual.getClass().getName() + "#" + contextual.hashCode();
086            }
087            
088            @Override
089            public Class<? extends Annotation> getScope() {
090                    return ViewScoped.class;
091            }
092            
093            @Override
094            public boolean isActive() {
095                    return getBeanCache() != null;
096            }
097            
098            public static class ViewBeanResetter<T> implements BeanResetter {
099                    
100                    private final Contextual<T> bean;
101                    private final CreationalContext<T> cc;
102                    
103                    public ViewBeanResetter(Contextual<T> bean, CreationalContext<T> cc) {
104                            this.bean = bean;
105                            this.cc = cc;
106                    }
107                    
108                    @SuppressWarnings("unchecked")
109                    public void reset(Object instance) {
110                            bean.destroy((T)instance, cc);
111                    }
112                    
113            }
114            
115    }
116