View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.cdi.view;
20  
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  import javax.enterprise.inject.spi.BeanManager;
28  import javax.faces.context.FacesContext;
29  import org.apache.myfaces.cdi.util.CDIUtils;
30  import org.apache.myfaces.cdi.util.ContextualInstanceInfo;
31  
32  /**
33   *
34   * @author Leonardo Uribe
35   */
36  public class ViewScopeCDIMap implements Map<String, Object>
37  {
38      private String _viewScopeId;
39      
40      private ViewScopeContextualStorage storage;
41  
42      public ViewScopeCDIMap(FacesContext facesContext)
43      {
44          BeanManager beanManager = CDIUtils.
45              getBeanManager(facesContext.getExternalContext());
46  
47          ViewScopeBeanHolder bean = CDIUtils.lookup(
48              beanManager, ViewScopeBeanHolder.class);
49  
50          // 1. get a new view scope id
51          _viewScopeId = bean.generateUniqueViewScopeId();
52  
53          storage = bean.
54              getContextualStorage(beanManager, _viewScopeId);
55      }
56      
57      public ViewScopeCDIMap(FacesContext facesContext, String viewScopeId)
58      {
59          BeanManager beanManager = CDIUtils.
60              getBeanManager(facesContext.getExternalContext());
61  
62          ViewScopeBeanHolder bean = CDIUtils.lookup(
63              beanManager, ViewScopeBeanHolder.class);
64  
65          // 1. get a new view scope id
66          _viewScopeId = viewScopeId;
67  
68          storage = bean.
69              getContextualStorage(beanManager, _viewScopeId);
70      }
71      
72      private ViewScopeContextualStorage getStorage()
73      {
74          if (storage != null && !storage.isActive())
75          {
76              storage = null;
77          }
78          if (storage == null)
79          {
80              FacesContext facesContext = FacesContext.getCurrentInstance();
81              BeanManager beanManager = CDIUtils.
82                  getBeanManager(facesContext.getExternalContext());
83  
84              ViewScopeBeanHolder bean = CDIUtils.lookup(
85                  beanManager, ViewScopeBeanHolder.class);
86              
87              storage = bean.
88                  getContextualStorage(beanManager, _viewScopeId);
89          }
90          return storage;
91      }
92      
93      private Map<String, Object> getNameBeanKeyMap()
94      {
95          return getStorage().getNameBeanKeyMap();
96      }
97      
98      private Map<Object, ContextualInstanceInfo<?>> getCreationalContextInstances()
99      {
100         return getStorage().getStorage();
101     }
102     
103     public String getViewScopeId()
104     {
105         return _viewScopeId;
106     }
107     
108     public int size()
109     {
110         return this.getNameBeanKeyMap().size();
111     }
112 
113     public boolean isEmpty()
114     {
115         return this.getNameBeanKeyMap().isEmpty();
116     }
117 
118     public boolean containsKey(Object key)
119     {
120         return this.getNameBeanKeyMap().containsKey(key);
121     }
122 
123     public boolean containsValue(Object value)
124     {
125         if (value != null)
126         {
127             for (Map.Entry<Object, ContextualInstanceInfo<?>> entry : 
128                 getCreationalContextInstances().entrySet())
129             {
130                 if (entry.getValue() != null &&
131                     value.equals(entry.getValue().getContextualInstance()))
132                 {
133                     return true;
134                 }
135             }
136         }
137         return false;
138     }
139 
140     public Object get(Object key)
141     {
142         Object beanKey = this.getNameBeanKeyMap().get(key);
143         if (beanKey != null)
144         {
145             ContextualInstanceInfo<?> info = this.getCreationalContextInstances().get(beanKey);
146             return info == null ? null : info.getContextualInstance();
147         }
148         return null;
149     }
150 
151     public Object put(String key, Object value)
152     {
153         Object beanKey = new _ContextualKey(key);
154         this.getNameBeanKeyMap().put(key, beanKey);
155         ContextualInstanceInfo info = new ContextualInstanceInfo();
156         info.setContextualInstance(value);
157         return this.getCreationalContextInstances().put(beanKey, info);
158     }
159 
160     public Object remove(Object key)
161     {
162         Object beanKey = this.getNameBeanKeyMap().remove(key);
163         ContextualInstanceInfo info = this.getCreationalContextInstances().remove(beanKey);
164         return info == null ? null : info.getContextualInstance();
165     }
166 
167     public void putAll(Map<? extends String, ? extends Object> m)
168     {
169         for (Map.Entry<? extends String, ? extends Object> entry : m.entrySet())
170         {
171             put(entry.getKey(), entry.getValue());
172         }
173     }
174 
175     public void clear()
176     {
177         boolean destroyed = false;
178         // If the scope was already destroyed through an invalidateSession(), the storage instance
179         // that is holding this map could be obsolete, so we need to grab the right instance from
180         // the bean holder.
181         FacesContext facesContext = FacesContext.getCurrentInstance();
182         if (facesContext != null)
183         {
184             BeanManager beanManager = CDIUtils.
185                 getBeanManager(facesContext.getExternalContext());
186 
187             if (beanManager != null)
188             {
189                 ViewScopeBeanHolder bean = CDIUtils.lookup(
190                     beanManager, ViewScopeBeanHolder.class);
191                 if (bean != null)
192                 {
193                     ViewScopeContextualStorage st = bean.
194                         getContextualStorage(beanManager, _viewScopeId);
195                     if (st != null)
196                     {
197                         ViewScopeContextImpl.destroyAllActive(st);
198                         storage = null;
199                         destroyed = true;
200                     }
201                 }
202             }
203         }
204         if (!destroyed)
205         {
206             ViewScopeContextImpl.destroyAllActive(storage);
207         }
208     }
209 
210     public Set<String> keySet()
211     {
212         return this.getNameBeanKeyMap().keySet();
213     }
214 
215     public Collection<Object> values()
216     {
217         List<Object> values = new ArrayList<Object>(this.getNameBeanKeyMap().size());
218         for (Map.Entry<String, Object> entry : 
219                 this.getNameBeanKeyMap().entrySet())
220         {
221             if (entry.getValue() != null)
222             {
223                 ContextualInstanceInfo info = 
224                     this.getCreationalContextInstances().get(entry.getValue());
225                 if (info != null)
226                 {
227                     values.add(info.getContextualInstance());
228                 }
229             }
230         }
231         return values;
232     }
233 
234     public Set<Entry<String, Object>> entrySet()
235     {
236         Set<Entry<String, Object>> values = new HashSet<Entry<String, Object>>();
237         for (Map.Entry<String, Object> entry : 
238                 this.getNameBeanKeyMap().entrySet())
239         {
240             if (entry.getValue() != null)
241             {
242                 ContextualInstanceInfo info = 
243                     this.getCreationalContextInstances().get(entry.getValue());
244                 if (info != null)
245                 {
246                     values.add(new EntryWrapper(entry));
247                 }
248             }
249         }
250         return values;
251     }
252     
253     private class EntryWrapper<String, Object> implements Entry<String, Object>
254     {
255         private Map.Entry<String, Object> entry;
256         
257         public EntryWrapper(Map.Entry<String, Object> entry)
258         {
259             this.entry = entry;
260         }
261 
262         public String getKey()
263         {
264             return entry.getKey();
265         }
266 
267         public Object getValue()
268         {
269             ContextualInstanceInfo<?> info = getCreationalContextInstances().get(entry.getValue());
270             return (Object) (info == null ? null : info.getContextualInstance());
271         }
272 
273         public Object setValue(Object value)
274         {
275             ContextualInstanceInfo info = getCreationalContextInstances().get(entry.getValue());
276             Object oldValue = null;
277             if (info != null)
278             {
279                 info.setContextualInstance(value);
280             }
281             else
282             {
283                 info = new ContextualInstanceInfo();
284                 info.setContextualInstance(value);
285                 getCreationalContextInstances().put(entry.getValue(), info);
286             }
287             return oldValue;
288         }
289     }
290 }