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.javafx.cdi;
022
023 import java.util.Set;
024
025 import javax.enterprise.context.ApplicationScoped;
026 import javax.enterprise.context.spi.CreationalContext;
027 import javax.enterprise.event.Observes;
028 import javax.enterprise.inject.Produces;
029 import javax.enterprise.inject.spi.AfterBeanDiscovery;
030 import javax.enterprise.inject.spi.AnnotatedMember;
031 import javax.enterprise.inject.spi.AnnotatedType;
032 import javax.enterprise.inject.spi.Bean;
033 import javax.enterprise.inject.spi.BeanManager;
034 import javax.enterprise.inject.spi.BeforeBeanDiscovery;
035 import javax.enterprise.inject.spi.Extension;
036 import javax.enterprise.inject.spi.InjectionPoint;
037 import javax.enterprise.inject.spi.InjectionTarget;
038 import javax.enterprise.inject.spi.ProcessInjectionTarget;
039 import javax.enterprise.inject.spi.ProcessProducer;
040 import javax.enterprise.inject.spi.Producer;
041 import javax.inject.Inject;
042
043 import org.granite.client.tide.Context;
044 import org.granite.client.tide.ContextAware;
045 import org.granite.client.tide.EventBus;
046 import org.granite.client.tide.NameAware;
047 import org.granite.client.tide.Platform;
048 import org.granite.client.tide.PlatformConfigurable;
049 import org.granite.client.tide.cdi.CDIContextManager;
050 import org.granite.client.tide.cdi.CDIEventBus;
051 import org.granite.client.tide.cdi.ViewContext;
052 import org.granite.client.tide.data.EntityManager;
053 import org.granite.client.tide.javafx.JavaFXDataManager;
054 import org.granite.client.tide.javafx.JavaFXPlatform;
055 import org.granite.logging.Logger;
056
057 /**
058 * @author William DRAI
059 */
060 public class JavaFXTideClientExtension implements Extension {
061
062 private static final Logger log = Logger.getLogger(JavaFXTideClientExtension.class);
063
064 private Platform platform = new JavaFXPlatform();
065
066
067 public void beforeBeanDiscovery(@Observes BeforeBeanDiscovery event, BeanManager beanManager) {
068 log.debug("Register internal Tide beans");
069 event.addAnnotatedType(beanManager.createAnnotatedType(JavaFXPlatform.class));
070 event.addAnnotatedType(beanManager.createAnnotatedType(CDIEventBus.class));
071 event.addAnnotatedType(beanManager.createAnnotatedType(JavaFXCDIContextManager.class));
072 }
073
074 public void afterBeanDiscovery(@Observes AfterBeanDiscovery event) {
075 log.debug("Register internal Tide scopes");
076 event.addContext(new ViewContext());
077 }
078
079 public void processProducer(@Observes ProcessProducer<Object, Object> event, BeanManager beanManager) {
080 event.setProducer(new ProducerWrapper<Object>(platform, beanManager, event.getProducer(), event.getAnnotatedMember()));
081 }
082
083 public void processInjectionTarget(@Observes ProcessInjectionTarget<Object> event, BeanManager beanManager) {
084 event.setInjectionTarget(new InjectionTargetWrapper<Object>(platform, beanManager, event.getInjectionTarget(), event.getAnnotatedType()));
085 }
086
087
088 @ApplicationScoped
089 public static class JavaFXCDIContextManager extends CDIContextManager {
090
091 protected JavaFXCDIContextManager() {
092 super();
093 // CDI proxying...
094 }
095
096 @Inject
097 public JavaFXCDIContextManager(Platform platform, EventBus eventBus) {
098 super(platform, eventBus);
099 }
100
101 @Produces
102 public Context getContext() {
103 return getContext(null);
104 }
105
106 @Produces
107 public EntityManager getEntityManager() {
108 return getContext(null).getEntityManager();
109 }
110
111 @Produces
112 public JavaFXDataManager getDataManager() {
113 return (JavaFXDataManager)super.getDataManager();
114 }
115 }
116
117 public static class ProducerWrapper<T> implements Producer<T> {
118
119 private Platform platform;
120 private BeanManager beanManager;
121 private Producer<T> producer;
122 private AnnotatedMember<T> annotatedMember;
123
124 public ProducerWrapper(Platform platform, BeanManager beanManager, Producer<T> producer, AnnotatedMember<T> annotatedMember) {
125 this.platform = platform;
126 this.beanManager = beanManager;
127 this.producer = producer;
128 this.annotatedMember = annotatedMember;
129 }
130
131 @Override
132 public void dispose(T instance) {
133 producer.dispose(instance);
134 }
135
136 @Override
137 public Set<InjectionPoint> getInjectionPoints() {
138 return producer.getInjectionPoints();
139 }
140
141 @Override
142 public T produce(CreationalContext<T> cc) {
143 T instance = producer.produce(cc);
144
145 if (instance instanceof NameAware) {
146 Set<Bean<?>> beans = beanManager.getBeans(annotatedMember.getBaseType());
147 if (beans.size() == 1)
148 ((NameAware)instance).setName(beans.iterator().next().getName());
149 }
150
151 if (instance instanceof ContextAware) {
152 Set<Bean<?>> beans = beanManager.getBeans(Context.class);
153 if (beans.size() == 1) {
154 Bean<?> bean = beans.iterator().next();
155 CreationalContext<?> ccc = beanManager.createCreationalContext(bean);
156 ((ContextAware)instance).setContext((Context)beanManager.getReference(bean, Context.class, ccc));
157 }
158 }
159
160 if (instance != null && instance.getClass().isAnnotationPresent(PlatformConfigurable.class))
161 platform.configure(instance);
162
163 return instance;
164 }
165 }
166
167 public static class InjectionTargetWrapper<T> implements InjectionTarget<T> {
168
169 private Platform platform;
170 private BeanManager beanManager;
171 private InjectionTarget<T> injectionTarget;
172 private AnnotatedType<T> annotatedType;
173
174 public InjectionTargetWrapper(Platform platform, BeanManager beanManager, InjectionTarget<T> injectionTarget, AnnotatedType<T> annotatedType) {
175 this.platform = platform;
176 this.beanManager = beanManager;
177 this.injectionTarget = injectionTarget;
178 this.annotatedType = annotatedType;
179 }
180
181 @Override
182 public void dispose(T instance) {
183 injectionTarget.dispose(instance);
184 }
185
186 @Override
187 public Set<InjectionPoint> getInjectionPoints() {
188 return injectionTarget.getInjectionPoints();
189 }
190
191 @Override
192 public void inject(T instance, CreationalContext<T> cc) {
193 injectionTarget.inject(instance, cc);
194 }
195
196 @Override
197 public T produce(CreationalContext<T> cc) {
198 return injectionTarget.produce(cc);
199 }
200
201 @Override
202 public void postConstruct(T instance) {
203 if (instance instanceof NameAware) {
204 Set<Bean<?>> beans = beanManager.getBeans(annotatedType.getBaseType());
205 if (beans.size() == 1)
206 ((NameAware)instance).setName(beans.iterator().next().getName());
207 }
208
209 if (instance instanceof ContextAware) {
210 Set<Bean<?>> beans = beanManager.getBeans(Context.class);
211 if (beans.size() == 1) {
212 Bean<?> bean = beans.iterator().next();
213 CreationalContext<?> ccc = beanManager.createCreationalContext(bean);
214 ((ContextAware)instance).setContext((Context)beanManager.getReference(bean, Context.class, ccc));
215 }
216 }
217
218 if (instance != null && instance.getClass().isAnnotationPresent(PlatformConfigurable.class))
219 platform.configure(instance);
220
221 injectionTarget.postConstruct(instance);
222 }
223
224 @Override
225 public void preDestroy(T instance) {
226 injectionTarget.preDestroy(instance);
227 }
228 }
229 }