001/*
002 * GWTEventService
003 * Copyright (c) 2011 and beyond, strawbill UG (haftungsbeschr?nkt)
004 *
005 * This is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU Lesser General Public License as
007 * published by the Free Software Foundation; either version 3 of
008 * the License, or (at your option) any later version.
009 * Other licensing for GWTEventService may also be possible on request.
010 * Please view the license.txt of the project for more information.
011 *
012 * This software is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this software; if not, write to the Free
019 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021 */
022package de.novanic.eventservice.client.event;
023
024import de.novanic.eventservice.client.config.EventServiceConfigurationTransferable;
025import de.novanic.eventservice.client.connection.callback.AsyncCallbackWrapper;
026import de.novanic.eventservice.client.connection.strategy.connector.ConnectionStrategyClientConnector;
027import de.novanic.eventservice.client.event.domain.Domain;
028import de.novanic.eventservice.client.event.filter.EventFilter;
029import de.novanic.eventservice.client.event.service.EventServiceAsync;
030import de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent;
031import de.novanic.eventservice.client.event.listener.unlisten.UnlistenEventListener;
032import com.google.gwt.user.client.rpc.AsyncCallback;
033import com.google.gwt.user.client.rpc.ServiceDefTarget;
034import de.novanic.eventservice.client.event.service.creator.EventServiceCreator;
035
036import java.util.Set;
037
038/**
039 * RemoteEventConnector should handle the connections between client- and the server side.
040 * GWTRemoteEventConnector uses the GWT-RPC mechanism to communicate with the server side.
041 *
042 * @author sstrohschein
043 *         <br>Date: 12.10.2008
044 *         <br>Time: 11:16:23
045 */
046public class GWTRemoteEventConnector extends DefaultRemoteEventConnector
047{
048    private EventServiceCreator myEventServiceCreator;
049    private EventServiceAsync myEventService;
050
051    /**
052     * Creates a new RemoteEventConnector with a connection to the corresponding EventService.
053     * @param aGWTEventServiceCreator factory to create the EventService for the connection
054     */
055    protected GWTRemoteEventConnector(EventServiceCreator aGWTEventServiceCreator) {
056        myEventServiceCreator = aGWTEventServiceCreator;
057        myEventService = aGWTEventServiceCreator.createEventService();
058    }
059
060    /**
061     * That method is called to execute the first server call (for initialization).
062     * @param aCallback callback
063     */
064    public void init(final AsyncCallback<EventServiceConfigurationTransferable> aCallback) {
065        myEventService.initEventService(new AsyncCallbackWrapper<EventServiceConfigurationTransferable>(aCallback) {
066            public void onSuccess(EventServiceConfigurationTransferable anEventServiceConfigurationTransferable) {
067                myEventService = refreshEventService(anEventServiceConfigurationTransferable.getConnectionId());
068                refreshConnectionStrategyClientConnector(anEventServiceConfigurationTransferable, myEventService);
069                super.onSuccess(anEventServiceConfigurationTransferable);
070            }
071        });
072    }
073
074    /**
075     * Initializes the listen method implementation with a {@link de.novanic.eventservice.client.connection.strategy.connector.ConnectionStrategyClientConnector} from the configuration.
076     * That is required to specify the listen / connection strategy. The connection strategy can't be changed, when the listening has already started / an listener was added.
077     * That implementation initializes the connection strategy with the {@link de.novanic.eventservice.client.event.service.EventService}.
078     * @param aConfiguration configuration
079     * @return initialized connection strategy connector
080     */
081    public ConnectionStrategyClientConnector initListen(EventServiceConfigurationTransferable aConfiguration) {
082        return initListen(aConfiguration, myEventService, false);
083    }
084
085    /**
086     * Initializes the listen method implementation with a {@link de.novanic.eventservice.client.connection.strategy.connector.ConnectionStrategyClientConnector} from the configuration.
087     * That is required to specify the listen / connection strategy. The connection strategy can't be changed, when the listening has already started / an listener was added.
088     * That implementation initializes the connection strategy with the {@link de.novanic.eventservice.client.event.service.EventService}.
089     * @param aConfiguration configuration
090     * @param anEventService event service (required for the connection strategy)
091     * @param isReinitialize decides if the initialization (init method) of the connection strategy connector is also executed when the connection strategy connector is already initialized
092     * (required for refreshes).
093     * @return initialized connection strategy connector
094     */
095    private ConnectionStrategyClientConnector initListen(EventServiceConfigurationTransferable aConfiguration, EventServiceAsync anEventService, boolean isReinitialize) {
096        ConnectionStrategyClientConnector theConnectionStrategyClientConnector = super.initListen(aConfiguration);
097        if(theConnectionStrategyClientConnector != null && (isReinitialize || !theConnectionStrategyClientConnector.isInitialized())) {
098            theConnectionStrategyClientConnector.init(anEventService);
099        }
100        return theConnectionStrategyClientConnector;
101    }
102
103    /**
104     * Activates the connector for the domain. An {@link de.novanic.eventservice.client.event.filter.EventFilter}
105     * to filter events on the server side is optional.
106     * @param aDomain domain to activate
107     * @param anEventFilter EventFilter to filter the events on the server side (optional)
108     * @param aCallback callback
109     */
110    public void activateStart(Domain aDomain, EventFilter anEventFilter, AsyncCallback<Void> aCallback) {
111        myEventService.register(aDomain, anEventFilter, aCallback);
112    }
113
114    /**
115     * Deactivates the connector for the domains (no events can be got from the domains).
116     * @param aDomains domains to deactivate
117     * @param aCallback callback
118     */
119    public void deactivate(Set<Domain> aDomains, AsyncCallback<Void> aCallback) {
120        myEventService.unlisten(aDomains, aCallback);
121    }
122
123    /**
124     * Deactivates the connector for the domain (no events can be got from the domain).
125     * @param aDomain domain to deactivate
126     * @param aCallback callback
127     */
128    public void deactivate(Domain aDomain, AsyncCallback<Void> aCallback) {
129        myEventService.unlisten(aDomain, aCallback);
130    }
131
132    /**
133     * Sends an event to a domain. The event will be received from all clients which are registered to that domain.
134     * User-specific events can be sent with the usage of this domain: {@link de.novanic.eventservice.client.event.domain.DomainFactory#USER_SPECIFIC_DOMAIN}.
135     * @param aDomain domain
136     * @param anEvent event
137     * @param aCallback callback
138     */
139    public void sendEvent(Domain aDomain, Event anEvent, AsyncCallback<Void> aCallback) {
140        myEventService.addEvent(aDomain, anEvent, aCallback);
141    }
142
143    /**
144     * Registers an {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} to the server side which
145     * will be triggered  when a timeout or unlisten/deactivation for a domain occurs.
146     * @param anUnlistenScope scope of the unlisten events to receive
147     * @param anUnlistenEvent {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} which can contain custom data
148     * @param aCallback callback
149     */
150    public void registerUnlistenEvent(UnlistenEventListener.Scope anUnlistenScope, UnlistenEvent anUnlistenEvent, AsyncCallback<Void> aCallback) {
151        super.registerUnlistenEvent(anUnlistenScope, anUnlistenEvent, aCallback);
152        //The UnlistenEvent mustn't be registered to the server side, when the scope is local.
153        if(UnlistenEventListener.Scope.LOCAL != anUnlistenScope) {
154            myEventService.registerUnlistenEvent(anUnlistenScope, anUnlistenEvent, aCallback);
155        }
156    }
157
158    /**
159     * Registers an {@link de.novanic.eventservice.client.event.filter.EventFilter} for a domain. That can be used when
160     * the domain is already activated and an {@link de.novanic.eventservice.client.event.filter.EventFilter} is
161     * needed later or isn't available when the domain becomes active.
162     * @param aDomain domain
163     * @param anEventFilter EventFilter to filter the events on the server side (optional)
164     * @param aCallback callback
165     */
166    public void registerEventFilter(Domain aDomain, EventFilter anEventFilter, AsyncCallback<Void> aCallback) {
167        myEventService.registerEventFilter(aDomain, anEventFilter, aCallback);
168    }
169
170    /**
171     * Deregisters the {@link de.novanic.eventservice.client.event.filter.EventFilter} for a domain.
172     * @param aDomain domain to remove the EventFilter from
173     * @param aCallback callback
174     */
175    public void deregisterEventFilter(Domain aDomain, AsyncCallback<Void> aCallback) {
176        myEventService.deregisterEventFilter(aDomain, aCallback);
177    }
178
179    /**
180     * Refreshes / re-initializes the {@link de.novanic.eventservice.client.event.service.EventService} when an explicit
181     * connection id is assigned for the client. When the connection id is NULL (no explicit connection id assigned), the
182     * {@link de.novanic.eventservice.client.event.service.EventService} will not be refreshed, because no separate connection
183     * id has to be transferred back to the server.
184     * @param aConnectionId connection id
185     * @return refreshed / re-initialized {@link de.novanic.eventservice.client.event.service.EventService}
186     */
187    private EventServiceAsync refreshEventService(String aConnectionId) {
188        if(aConnectionId != null) {
189            EventServiceAsync theEventService = myEventServiceCreator.createEventService();
190
191            final ServiceDefTarget theServiceDefTarget = (ServiceDefTarget)theEventService;
192            theServiceDefTarget.setServiceEntryPoint(theServiceDefTarget.getServiceEntryPoint() + "?id=" + aConnectionId);
193
194            return theEventService;
195        }
196        return myEventService;
197    }
198
199    /**
200     * Refreshes or creates the connection strategy connector.
201     * @param aConfiguration configuration
202     * @param anEventService event service (required for the connection strategy)
203     * @return initialized connection strategy connector
204     */
205    private ConnectionStrategyClientConnector refreshConnectionStrategyClientConnector(EventServiceConfigurationTransferable aConfiguration, EventServiceAsync anEventService) {
206        return initListen(aConfiguration, anEventService, true);
207    }
208}