EMMA Coverage Report (generated Sat Apr 14 15:01:05 EDT 2012)
[all classes][org.deduced.viewer.web.shared]

COVERAGE SUMMARY FOR SOURCE FILE [ModelRegistry.java]

nameclass, %method, %block, %line, %
ModelRegistry.java100% (8/8)92%  (59/64)95%  (760/803)94%  (229/244)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ModelRegistry$LinkedAsyncCallback100% (1/1)60%  (3/5)62%  (18/29)60%  (6/10)
getLinkedCallback (): AsyncCallback 0%   (0/1)0%   (0/3)0%   (0/1)
onFailure (Throwable): void 0%   (0/1)0%   (0/8)0%   (0/3)
ModelRegistry$LinkedAsyncCallback (ModelRegistry): void 100% (1/1)100% (6/6)100% (1/1)
onSuccess (Object): void 100% (1/1)100% (8/8)100% (3/3)
setLinkedCallback (AsyncCallback): void 100% (1/1)100% (4/4)100% (2/2)
     
class ModelRegistry$UpdatePropertyCallback100% (1/1)88%  (7/8)84%  (32/38)81%  (13/16)
onFailure (Throwable): void 0%   (0/1)0%   (0/6)0%   (0/3)
ModelRegistry$UpdatePropertyCallback (ModelRegistry): void 100% (1/1)100% (7/7)100% (2/2)
getChangeEvent (): ChangeEvent 100% (1/1)100% (3/3)100% (1/1)
getChangeEventLocation (): ChangeEvent 100% (1/1)100% (3/3)100% (1/1)
onSuccess (Void): void 100% (1/1)100% (6/6)100% (3/3)
setChangeEvent (ChangeEvent): void 100% (1/1)100% (4/4)100% (2/2)
setChangeEventLocation (ChangeEvent): void 100% (1/1)100% (4/4)100% (2/2)
updateCompleted (): void 100% (1/1)100% (5/5)100% (2/2)
     
class ModelRegistry100% (1/1)95%  (36/38)96%  (634/660)96%  (187/195)
getRootWidgetControl (): RootWidgetControl 0%   (0/1)0%   (0/3)0%   (0/1)
signalTriggered (String, String, AsyncCallback): void 0%   (0/1)0%   (0/11)0%   (0/3)
getLatestEventsFinished (): void 100% (1/1)60%  (9/15)67%  (4/6)
getLatestEvents (): void 100% (1/1)84%  (16/19)83%  (5/6)
updateProperty (String, String, Serializable, AsyncCallback): void 100% (1/1)97%  (104/107)97%  (30/31)
ModelRegistry (): void 100% (1/1)100% (32/32)100% (9/9)
addEventToIgnoreList (ChangeEvent): void 100% (1/1)100% (21/21)100% (6/6)
addIgnoreAddEvents (String, List, List): void 100% (1/1)100% (48/48)100% (14/14)
addIgnoreRemoveEvents (String, List, List): void 100% (1/1)100% (48/48)100% (14/14)
cancelPollingTimer (): void 100% (1/1)100% (8/8)100% (4/4)
cleanEventsOlderThanMinimumTimeValue (long, long): void 100% (1/1)100% (38/38)100% (12/12)
cleanOldEvents (): void 100% (1/1)100% (11/11)100% (4/4)
createRefreshTimer (): void 100% (1/1)100% (7/7)100% (2/2)
createUIRefreshLinkedCallback (AsyncCallback): AsyncCallback 100% (1/1)100% (10/10)100% (3/3)
getDefaultVoidCallback (): AsyncCallback 100% (1/1)100% (3/3)100% (1/1)
getErrorLabel (): Label 100% (1/1)100% (18/18)100% (5/5)
getIgnoreChangeEventMap (): Map 100% (1/1)100% (3/3)100% (1/1)
getInitialUserInterface (): void 100% (1/1)100% (8/8)100% (2/2)
getModel (String): Model 100% (1/1)100% (6/6)100% (1/1)
getRefreshTimer (): Timer 100% (1/1)100% (3/3)100% (1/1)
getUserInterfaceService (): DynamicUserInterfaceServiceAsync 100% (1/1)100% (3/3)100% (1/1)
handleChangeEvent (ChangeEvent): void 100% (1/1)100% (17/17)100% (6/6)
handleChangeEventList (List): void 100% (1/1)100% (17/17)100% (4/4)
handleChangeEventSilent (ChangeEvent): void 100% (1/1)100% (9/9)100% (5/5)
initializeUserInterface (ViewModel): void 100% (1/1)100% (18/18)100% (7/7)
isEventIgnored (ChangeEvent): boolean 100% (1/1)100% (24/24)100% (8/8)
monitorSynchronizeWithUI (UserInterfaceModel): void 100% (1/1)100% (1/1)100% (1/1)
propertyUpdateCompleted (ModelRegistry$UpdatePropertyCallback): void 100% (1/1)100% (37/37)100% (8/8)
registerModel (Model): void 100% (1/1)100% (8/8)100% (2/2)
setRootWidgetControl (RootWidgetControl): void 100% (1/1)100% (4/4)100% (2/2)
setUserInterfaceService (DynamicUserInterfaceServiceAsync): void 100% (1/1)100% (4/4)100% (2/2)
showErrorException (String, Throwable): void 100% (1/1)100% (16/16)100% (3/3)
showErrorException (Throwable): void 100% (1/1)100% (14/14)100% (3/3)
showErrorLabel (String): void 100% (1/1)100% (7/7)100% (3/3)
showExpiredChangeEventWarning (long, long, ChangeEvent): void 100% (1/1)100% (25/25)100% (3/3)
startServerPollingTimer (): void 100% (1/1)100% (9/9)100% (4/4)
unRegisterModel (Model): void 100% (1/1)100% (7/7)100% (2/2)
updateReferenceList (String, ArrayList, ArrayList, AsyncCallback): void 100% (1/1)100% (21/21)100% (5/5)
     
class ModelRegistry$1100% (1/1)100% (3/3)100% (17/17)100% (5/5)
ModelRegistry$1 (ModelRegistry): void 100% (1/1)100% (6/6)100% (1/1)
onFailure (Throwable): void 100% (1/1)100% (6/6)100% (2/2)
onSuccess (ViewModel): void 100% (1/1)100% (5/5)100% (2/2)
     
class ModelRegistry$2100% (1/1)100% (2/2)100% (10/10)100% (3/3)
ModelRegistry$2 (ModelRegistry): void 100% (1/1)100% (6/6)100% (1/1)
run (): void 100% (1/1)100% (4/4)100% (2/2)
     
class ModelRegistry$3100% (1/1)100% (3/3)100% (23/23)100% (7/7)
ModelRegistry$3 (ModelRegistry): void 100% (1/1)100% (6/6)100% (1/1)
onFailure (Throwable): void 100% (1/1)100% (9/9)100% (3/3)
onSuccess (ArrayList): void 100% (1/1)100% (8/8)100% (3/3)
     
class ModelRegistry$ErrorReportCallback100% (1/1)100% (3/3)100% (12/12)100% (4/4)
ModelRegistry$ErrorReportCallback (ModelRegistry): void 100% (1/1)100% (6/6)100% (1/1)
onFailure (Throwable): void 100% (1/1)100% (5/5)100% (2/2)
onSuccess (Void): void 100% (1/1)100% (1/1)100% (1/1)
     
class ModelRegistry$RefreshUiOnSuccessLinkedAsyncCallback100% (1/1)100% (2/2)100% (14/14)100% (4/4)
ModelRegistry$RefreshUiOnSuccessLinkedAsyncCallback (ModelRegistry): void 100% (1/1)100% (7/7)100% (1/1)
onSuccess (Object): void 100% (1/1)100% (7/7)100% (3/3)

1/**
2 *    Copyright 2005-2011 Steve McDuff d-duff@users.sourceforge.net
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.deduced.viewer.web.shared;
17 
18import java.io.Serializable;
19import java.util.ArrayList;
20import java.util.HashMap;
21import java.util.Iterator;
22import java.util.List;
23import java.util.Map;
24import java.util.Map.Entry;
25import java.util.Set;
26 
27import com.google.gwt.user.client.Timer;
28import com.google.gwt.user.client.rpc.AsyncCallback;
29import com.google.gwt.user.client.ui.Label;
30import com.google.gwt.user.client.ui.RootPanel;
31 
32/**
33 * The Model Registry is the central class on the client side. It registers all
34 * the models, dispatches change events and allows the models to reach back to
35 * the server.
36 * 
37 * @author Steve McDuff
38 * 
39 */
40public class ModelRegistry
41{
42        /**
43         * amount of time to wait between server pooling request in milliseconds.
44         */
45        public static final int SERVER_POLLING_LOOP_DELAY_IN_MILLISECONDS = 1000;
46 
47        /**
48         * maximum ignore event age in milliseconds
49         */
50        private static final int MAXIMUM_IGNORE_EVENT_AGE_IN_MILLISECONDS =
51                5 * 60 * 1000;
52 
53        /**
54         * map of all the registered models based on their unique ID key.
55         */
56        private Map<String, Model> registry = new HashMap<String, Model>();
57 
58        /**
59         * the User Interface Service used to call the server
60         */
61        private DynamicUserInterfaceServiceAsync userInterfaceService;
62 
63        /**
64         * default void server call back
65         */
66        private final ErrorReportCallback callBack = new ErrorReportCallback();
67 
68        /**
69         * map of all the change events to ignore
70         */
71        private Map<ChangeEvent, IgnoredEventInformation> ignoreChangeEventMap =
72                new HashMap<ChangeEvent, IgnoredEventInformation>();
73 
74        /**
75         * map of all the update property that haven't been sent yet
76         */
77        private Map<ChangeEvent, PendingChangeEvent> pendingChangeEventMap =
78                new HashMap<ChangeEvent, PendingChangeEvent>();
79 
80        /**
81         * error label
82         */
83        private Label errorLabel;
84 
85        /**
86         * Timer used to poll the server for updates.
87         */
88        private Timer refreshTimer;
89 
90        /**
91         * root widget control
92         */
93        private RootWidgetControl rootWidgetControl;
94 
95        /**
96         * is the get latest event method currently waiting for results from the
97         * server.
98         */
99        private boolean getLatestEventsIsRunning = false;
100 
101        /**
102         * Should the getLatestEvent method be called when it finishes it's current
103         * execution.
104         */
105        private boolean getLatestEventsRunAgain = false;
106 
107        /**
108         * ModelRegistry constructor
109         */
110        public ModelRegistry()
111        {
112                createRefreshTimer();
113        }
114 
115        /**
116         * get RootWidgetControl
117         * 
118         * @return root widget control
119         */
120        public RootWidgetControl getRootWidgetControl()
121        {
122                return rootWidgetControl;
123        }
124 
125        /**
126         * set RootWidgetControl
127         * 
128         * @param setRootWidgetControl the new root widget control
129         */
130        public void setRootWidgetControl(
131                RootWidgetControl setRootWidgetControl)
132        {
133                rootWidgetControl = setRootWidgetControl;
134        }
135 
136        /**
137         * start Server Polling Timer
138         */
139        public void startServerPollingTimer()
140        {
141                Timer currentRefreshTimer = getRefreshTimer();
142                if (currentRefreshTimer != null)
143                {
144                        currentRefreshTimer
145                                .schedule(SERVER_POLLING_LOOP_DELAY_IN_MILLISECONDS);
146                }
147        }
148 
149        /**
150         * get Initial User Interface
151         */
152        public void getInitialUserInterface()
153        {
154                getUserInterfaceService().getInitialUserInterface(
155                        new AsyncCallback<ViewModel>()
156                        {
157                                @Override
158                                public void onSuccess(
159                                        ViewModel result)
160                                {
161                                        initializeUserInterface(result);
162                                }
163 
164                                @Override
165                                public void onFailure(
166                                        Throwable caught)
167                                {
168                                        showErrorException("getInitialUserInterface failed", caught);
169                                }
170 
171                        });
172        }
173 
174        /**
175         * initialize the User Interface
176         * 
177         * @param rootModel the root model to use
178         */
179        public void initializeUserInterface(
180                ViewModel rootModel)
181        {
182                if (rootModel != null)
183                {
184                        rootModel.registerModel(this);
185 
186                        rootModel.setRootWidgetControl(rootWidgetControl);
187                        rootModel.synchronizeWithUI();
188 
189                        // Setup timer to gather UI changes
190                        startServerPollingTimer();
191                }
192                else
193                {
194                        showErrorLabel("getInitialUserInterface returned null.");
195                }
196        }
197 
198        /**
199         * signal Triggered
200         * 
201         * @param objectID object ID
202         * @param signalName signal name
203         * @param callback call back interface
204         */
205        public void signalTriggered(
206                String objectID, String signalName, AsyncCallback<Void> callback)
207        {
208                AsyncCallback<Void> callBackToUse =
209                        createUIRefreshLinkedCallback(callback);
210 
211                getUserInterfaceService().signalTriggered(objectID, signalName,
212                        callBackToUse);
213        }
214 
215        /**
216         * create Refresh Timer
217         */
218        public void createRefreshTimer()
219        {
220                refreshTimer = new Timer()
221                {
222                        /**
223                         * (non-JSDoc)
224                         * 
225                         * @see com.google.gwt.user.client.Timer#run()
226                         */
227                        @Override
228                        public void run()
229                        {
230                                getLatestEvents();
231                        }
232                };
233        }
234 
235        /**
236         * call the server to get the latest update events and handle them.
237         */
238        public void getLatestEvents()
239        {
240                if (getLatestEventsIsRunning)
241                {
242                        getLatestEventsRunAgain = true;
243                }
244 
245                getLatestEventsIsRunning = true;
246                cancelPollingTimer();
247                getUserInterfaceService().getChangeEventList(
248                        new AsyncCallback<ArrayList<ChangeEvent>>()
249                        {
250 
251                                @Override
252                                public void onFailure(
253                                        Throwable caught)
254                                {
255                                        getLatestEventsFinished();
256                                        showErrorException("getLatestEvents failed", caught);
257                                }
258 
259                                @Override
260                                public void onSuccess(
261                                        ArrayList<ChangeEvent> result)
262                                {
263                                        getLatestEventsFinished();
264                                        handleChangeEventList(result);
265                                }
266                        });
267        }
268 
269        /**
270         * get Latest Events Finished
271         */
272        public void getLatestEventsFinished()
273        {
274                getLatestEventsIsRunning = false;
275 
276                if (getLatestEventsRunAgain)
277                {
278                        getLatestEventsRunAgain = false;
279                        getLatestEvents();
280                }
281                else
282                {
283                        startServerPollingTimer();
284                }
285        }
286 
287        /**
288         * cancel Polling Timer
289         */
290        public void cancelPollingTimer()
291        {
292                Timer currentRrefreshTimer = getRefreshTimer();
293                if (currentRrefreshTimer != null)
294                {
295                        currentRrefreshTimer.cancel();
296                }
297        }
298 
299        /**
300         * handle a list of Change Event from the serverList
301         * 
302         * @param changeEventList the list of change event to process
303         */
304        public void handleChangeEventList(
305                List<ChangeEvent> changeEventList)
306        {
307                if (changeEventList != null)
308                {
309                        for (ChangeEvent changeEvent : changeEventList)
310                        {
311                                handleChangeEventSilent(changeEvent);
312                        }
313                }
314        }
315 
316        /**
317         * get Refresh Timer
318         * 
319         * @return the refresh timer
320         */
321        public Timer getRefreshTimer()
322        {
323                return refreshTimer;
324        }
325 
326        /**
327         * get the User Interface Service used to call the server
328         * 
329         * @return the User Interface Service used to call the server
330         */
331        public DynamicUserInterfaceServiceAsync getUserInterfaceService()
332        {
333                return userInterfaceService;
334        }
335 
336        /**
337         * set the User Interface Service to use
338         * 
339         * @param setUserInterfaceService the asynchronous user interface service to
340         *            call.
341         */
342        public void setUserInterfaceService(
343                DynamicUserInterfaceServiceAsync setUserInterfaceService)
344        {
345                userInterfaceService = setUserInterfaceService;
346        }
347 
348        /**
349         * register Model. Once registered, a model can be found based on it's
350         * unique ID and it can receive change events.
351         * 
352         * @param model the model to register
353         */
354        public void registerModel(
355                Model model)
356        {
357                registry.put(model.getId(), model);
358        }
359 
360        /**
361         * unregister a Model
362         * 
363         * @param model the model to unregister
364         */
365        public void unRegisterModel(
366                Model model)
367        {
368                registry.remove(model.getId());
369        }
370 
371        /**
372         * get Model based on it's id
373         * 
374         * @param id the model ID
375         * @return the matching model. Null if the ID can't be found.
376         */
377        public Model getModel(
378                String id)
379        {
380                return registry.get(id);
381        }
382 
383        /**
384         * handle Change Event by dispatching it to the model that matches the
385         * change event ID and hiding any caught exception.
386         * 
387         * @param changeEvent the change event to handle
388         */
389        public void handleChangeEventSilent(
390                ChangeEvent changeEvent)
391        {
392                try
393                {
394                        handleChangeEvent(changeEvent);
395                }
396                catch (Exception e)
397                {
398                        showErrorException(e);
399                }
400        }
401 
402        /**
403         * handle Change Event by dispatching it to the model that matches the
404         * change event ID
405         * 
406         * @param changeEvent the change event to dispatch
407         */
408        public void handleChangeEvent(
409                ChangeEvent changeEvent)
410        {
411                if (changeEvent != null)
412                {
413                        if (!isEventIgnored(changeEvent))
414                        {
415                                Model model = getModel(changeEvent.getId());
416 
417                                if (model != null)
418                                {
419                                        model.propertyChanged(changeEvent);
420                                }
421                        }
422                }
423        }
424 
425        /**
426         * show Error Exception on the UI. Called by models who want to report
427         * problems directly to the user interface. This is meant mostly for
428         * internal type of errors.
429         * 
430         * @param description error message to display on top of the exception.
431         * @param caught the exception to display
432         */
433        public void showErrorException(
434                String description, Throwable caught)
435        {
436                String errorText = description + " : " + caught.getMessage();
437                showErrorLabel(errorText);
438        }
439 
440        /**
441         * show Error Exception on the UI. Called by models who want to report
442         * problems directly to the user interface. This is meant mostly for
443         * internal type of errors.
444         * 
445         * @param caught the exception to display
446         */
447        public void showErrorException(
448                Throwable caught)
449        {
450                String errorText = "Exception Caught : " + caught.getMessage();
451                showErrorLabel(errorText);
452        }
453 
454        /**
455         * show an Error Label on the UI. Called by models who want to report
456         * problems directly to the user interface. This is meant mostly for
457         * internal type of errors.
458         * 
459         * @param errorText the error text to display.
460         */
461        public void showErrorLabel(
462                String errorText)
463        {
464                Label currentErrorLabel = getErrorLabel();
465                currentErrorLabel.setText(errorText);
466        }
467 
468        /**
469         * get Error Label
470         * 
471         * @return the error label
472         */
473        public Label getErrorLabel()
474        {
475                if (errorLabel == null)
476                {
477                        errorLabel = new Label();
478                        RootPanel rootPanel = RootPanel.get("dynamicView");
479                        Utilities.addWidgetToPanel(errorLabel, rootPanel);
480                }
481                return errorLabel;
482        }
483 
484        /**
485         * get the Default Void server Call back
486         * 
487         * @return the Default Void server Call back
488         */
489        public AsyncCallback<Void> getDefaultVoidCallback()
490        {
491                return callBack;
492        }
493 
494        /**
495         * Server update Error Report Call back
496         * 
497         * @author Steve McDuff
498         * 
499         */
500        public class ErrorReportCallback implements AsyncCallback<Void>
501        {
502 
503                /**
504                 * (non-JSDoc)
505                 * 
506                 * @see com.google.gwt.user.client.rpc.AsyncCallback#onFailure(java.lang.Throwable)
507                 */
508                @Override
509                public void onFailure(
510                        Throwable caught)
511                {
512                        showErrorException(caught);
513                }
514 
515                /**
516                 * (non-JSDoc)
517                 * 
518                 * @see com.google.gwt.user.client.rpc.AsyncCallback#onSuccess(java.lang.Object)
519                 */
520                @Override
521                public void onSuccess(
522                        Void result)
523                {
524 
525                }
526        }
527 
528        /**
529         * Linked asynchronous call backs will have a chance to do work before or
530         * after their link is invoked.
531         * 
532         * @author Steve McDuff
533         * @param <T> type value returned in the call back
534         * 
535         */
536        public class LinkedAsyncCallback<T> implements AsyncCallback<T>
537        {
538 
539                /**
540                 * optional linked call back
541                 */
542                private AsyncCallback<T> linkedCallback;
543 
544                /**
545                 * get Linked Call back
546                 * 
547                 * @return linked call back
548                 */
549                public AsyncCallback<T> getLinkedCallback()
550                {
551                        return linkedCallback;
552                }
553 
554                /**
555                 * set Linked Call back
556                 * 
557                 * @param setLinkedCallback the new linked call back
558                 */
559                public void setLinkedCallback(
560                        AsyncCallback<T> setLinkedCallback)
561                {
562                        linkedCallback = setLinkedCallback;
563                }
564 
565                /**
566                 * (non-JSDoc)
567                 * 
568                 * @see com.google.gwt.user.client.rpc.AsyncCallback#onFailure(java.lang.Throwable)
569                 */
570                @Override
571                public void onFailure(
572                        Throwable caught)
573                {
574                        if (linkedCallback != null)
575                        {
576                                linkedCallback.onFailure(caught);
577                        }
578                }
579 
580                /**
581                 * (non-JSDoc)
582                 * 
583                 * @see com.google.gwt.user.client.rpc.AsyncCallback#onSuccess(java.lang.Object)
584                 */
585                @Override
586                public void onSuccess(
587                        T result)
588                {
589                        if (linkedCallback != null)
590                        {
591                                linkedCallback.onSuccess(result);
592                        }
593                }
594        }
595 
596        /**
597         * Server update Error Report Call back
598         * 
599         * @author Steve McDuff
600         * @param <T> type value returned in the call back
601         * 
602         */
603        public class RefreshUiOnSuccessLinkedAsyncCallback<T> extends
604                LinkedAsyncCallback<T>
605        {
606                /**
607                 * (non-JSDoc)
608                 * 
609                 * @see com.google.gwt.user.client.rpc.AsyncCallback#onSuccess(java.lang.Object)
610                 */
611                @Override
612                public void onSuccess(
613                        T result)
614                {
615                        super.onSuccess(result);
616 
617                        // fetch the latest events right after a successful change to get
618                        // the UI to reflect the latest changes without waiting for the
619                        // polling loop.
620                        getLatestEvents();
621                }
622        }
623 
624        /**
625         * call back used to trap property updates that might be pending
626         * 
627         * @author Steve McDuff
628         * 
629         */
630        public class UpdatePropertyCallback extends
631                RefreshUiOnSuccessLinkedAsyncCallback<Void>
632        {
633 
634                /**
635                 * which property was changed on which object
636                 */
637                private ChangeEvent changeEventLocation;
638 
639                /**
640                 * actual updated value change event
641                 */
642                private ChangeEvent changeEvent;
643 
644                /**
645                 * 
646                 * UpdatePropertyCallback constructor
647                 */
648                public UpdatePropertyCallback()
649                {
650 
651                }
652 
653                /**
654                 * get Change Event
655                 * 
656                 * @return the change event
657                 */
658                public ChangeEvent getChangeEvent()
659                {
660                        return changeEvent;
661                }
662 
663                /**
664                 * set Change Event Location
665                 * 
666                 * @param setChangeEventLocation new change event
667                 */
668                public void setChangeEventLocation(
669                        ChangeEvent setChangeEventLocation)
670                {
671                        changeEventLocation = setChangeEventLocation;
672                }
673 
674                /**
675                 * get Change Event Location
676                 * 
677                 * @return change event location
678                 */
679                public ChangeEvent getChangeEventLocation()
680                {
681                        return changeEventLocation;
682                }
683 
684                /**
685                 * 
686                 * set Change Event
687                 * 
688                 * @param setChangeEvent new change event
689                 */
690                public void setChangeEvent(
691                        ChangeEvent setChangeEvent)
692                {
693                        changeEvent = setChangeEvent;
694                }
695 
696                /**
697                 * (non-JSDoc)
698                 * 
699                 * @see com.google.gwt.user.client.rpc.AsyncCallback#onFailure(java.lang.Throwable)
700                 */
701                @Override
702                public void onFailure(
703                        Throwable caught)
704                {
705                        updateCompleted();
706                        super.onFailure(caught);
707                }
708 
709                /**
710                 * (non-JSDoc)
711                 * 
712                 * @see com.google.gwt.user.client.rpc.AsyncCallback#onSuccess(java.lang.Object)
713                 */
714                @Override
715                public void onSuccess(
716                        Void result)
717                {
718                        updateCompleted();
719                        super.onSuccess(result);
720                }
721 
722                /**
723                 * update Completed
724                 */
725                public void updateCompleted()
726                {
727                        propertyUpdateCompleted(this);
728                }
729        }
730 
731        /**
732         * 
733         * propertyUpdateCompleted
734         * 
735         * @param callback change event call back
736         */
737        protected void propertyUpdateCompleted(
738                UpdatePropertyCallback callback)
739        {
740                ChangeEvent changeEventLocation = callback.getChangeEventLocation();
741                PendingChangeEvent pendingEvent =
742                        pendingChangeEventMap.remove(changeEventLocation);
743                if (pendingEvent != null && !pendingEvent.isSent())
744                {
745                        // discovered a pending change, send it to the server assuming the
746                        // new value is different.
747                        ChangeEvent newEvent = pendingEvent.getEvent();
748 
749                        ChangeEvent oldChangeEvent = callback.getChangeEvent();
750                        if (!Utilities.equals(oldChangeEvent.getSerializableValue(),
751                                newEvent.getSerializableValue()))
752                        {
753                                updateProperty(newEvent.getId(), newEvent.getName(),
754                                        newEvent.getSerializableValue(), pendingEvent.getCallback());
755                        }
756                }
757        }
758 
759        /**
760         * update Property and ignore the incoming change event. Also stack similar
761         * changes together and ignore older ones.
762         * 
763         * @param objectID object ID that changed
764         * @param propertyName property name to change
765         * @param newValue new value
766         * @param callback call back interface
767         */
768        public void updateProperty(
769                String objectID, String propertyName, Serializable newValue,
770                AsyncCallback<Void> callback)
771        {
772                ChangeEvent pendingEventLocation = new ChangeEvent();
773 
774                pendingEventLocation.setId(objectID);
775                pendingEventLocation.setName(propertyName);
776                pendingEventLocation.setValue(null);
777                pendingEventLocation.setType("update");
778                pendingEventLocation.setSortingInstance(false);
779 
780                ChangeEvent ignoreEvent = new ChangeEvent();
781 
782                ignoreEvent.setId(objectID);
783                ignoreEvent.setName(propertyName);
784                ignoreEvent.setValue(Serializer.serialize(newValue));
785                ignoreEvent.setType("update");
786                ignoreEvent.setSortingInstance(false);
787 
788                PendingChangeEvent pending = new PendingChangeEvent();
789                pending.setCallback(callback);
790                pending.setEvent(ignoreEvent);
791 
792                PendingChangeEvent removedPendingEvent =
793                        pendingChangeEventMap.remove(pendingEventLocation);
794                if (removedPendingEvent != null)
795                {
796                        AsyncCallback<Void> cancelledCallback =
797                                removedPendingEvent.getCallback();
798                        if (cancelledCallback != null)
799                        {
800                                cancelledCallback.onSuccess(null);
801                        }
802 
803                        // there is already an update of this property going on, buffer this
804                        // one.
805                        pendingChangeEventMap.put(pendingEventLocation, pending);
806                }
807                else
808                {
809                        addEventToIgnoreList(ignoreEvent);
810 
811                        UpdatePropertyCallback updateCallBack =
812                                new UpdatePropertyCallback();
813                        updateCallBack.setChangeEvent(ignoreEvent);
814                        updateCallBack.setChangeEventLocation(pendingEventLocation);
815                        updateCallBack.setLinkedCallback(callback);
816 
817                        pending.setSent(true);
818                        pendingChangeEventMap.put(pendingEventLocation, pending);
819 
820                        getUserInterfaceService().updateProperty(objectID, propertyName,
821                                Serializer.serialize(newValue), updateCallBack);
822                }
823        }
824 
825        /**
826         * add Event To Ignore List
827         * 
828         * @param ignoreEvent event to ignore
829         */
830        public void addEventToIgnoreList(
831                ChangeEvent ignoreEvent)
832        {
833                IgnoredEventInformation iei = ignoreChangeEventMap.get(ignoreEvent);
834                if (iei == null)
835                {
836                        iei = new IgnoredEventInformation();
837                        ignoreChangeEventMap.put(ignoreEvent, iei);
838                }
839                iei.incrementIgnoredCount();
840        }
841 
842        /**
843         * clean Old Events : parse the list of ignored change events to see if some
844         * of them are too old.
845         */
846        public void cleanOldEvents()
847        {
848                long currentTime = Utilities.getTimeStampInMilliseconds();
849 
850                long minimumTimeValue =
851                        currentTime - MAXIMUM_IGNORE_EVENT_AGE_IN_MILLISECONDS;
852 
853                cleanEventsOlderThanMinimumTimeValue(currentTime, minimumTimeValue);
854        }
855 
856        /**
857         * 
858         * clean Events Older Than Minimum Time Value
859         * 
860         * @param currentTime current time
861         * @param minimumTimeValue minimum time value
862         */
863        public void cleanEventsOlderThanMinimumTimeValue(
864                long currentTime, long minimumTimeValue)
865        {
866                Set<Entry<ChangeEvent, IgnoredEventInformation>> entrySet =
867                        ignoreChangeEventMap.entrySet();
868 
869                for (Iterator<Entry<ChangeEvent, IgnoredEventInformation>> iterator =
870                        entrySet.iterator(); iterator.hasNext();)
871                {
872                        Entry<ChangeEvent, IgnoredEventInformation> entry = iterator.next();
873 
874                        IgnoredEventInformation value = entry.getValue();
875 
876                        // the time stamp of the event to ignore is too old, delete it.
877                        long eventTime = value.getIgnoredTimeStamp();
878                        if (eventTime < minimumTimeValue)
879                        {
880                                ChangeEvent expiredEvent = entry.getKey();
881 
882                                showExpiredChangeEventWarning(currentTime, eventTime,
883                                        expiredEvent);
884 
885                                iterator.remove();
886                        }
887                }
888        }
889 
890        /**
891         * show Expired Change Event Warning
892         * 
893         * @param currentTime the current time
894         * @param eventTime the event time
895         * @param expiredEvent the expired event
896         */
897        public void showExpiredChangeEventWarning(
898                long currentTime, long eventTime, ChangeEvent expiredEvent)
899        {
900                String errorText =
901                        "Found expired change event : Change Event Timestamp is : "
902                                + eventTime + " ms, current time is : " + currentTime
903                                + " ms. Exceeds maximum delay of : "
904                                + MAXIMUM_IGNORE_EVENT_AGE_IN_MILLISECONDS + " ms. "
905                                + expiredEvent;
906 
907                showErrorLabel(errorText);
908        }
909 
910        /**
911         * is a change Event Ignored since it was first created by the client
912         * 
913         * @param changeEvent the change event to potentially ignore
914         * @return true if we can ignore the change event
915         */
916        public boolean isEventIgnored(
917                ChangeEvent changeEvent)
918        {
919                boolean ignored = false;
920                IgnoredEventInformation ignoredEventInformation =
921                        ignoreChangeEventMap.get(changeEvent);
922                if (ignoredEventInformation != null)
923                {
924                        // the event must be ignored.
925 
926                        // decrement the number of times the event must be ignored
927                        boolean removeInfo =
928                                ignoredEventInformation.decrementIgnoredCount();
929                        if (removeInfo)
930                        {
931                                // the ignore count reached zero, we can forget about this
932                                // event.
933                                ignoreChangeEventMap.remove(changeEvent);
934                        }
935                        ignored = true;
936                }
937                return ignored;
938        }
939 
940        /**
941         * get Ignore Change Event Map
942         * 
943         * @return the ignored change event map
944         */
945        public Map<ChangeEvent, IgnoredEventInformation> getIgnoreChangeEventMap()
946        {
947                return ignoreChangeEventMap;
948        }
949 
950        /**
951         * monitor Synchronize With UI event. By default, this method does nothing.
952         * Overriding it allows users to monitor synchronization events.
953         * 
954         * @param model the model being synchronized
955         */
956        public void monitorSynchronizeWithUI(
957                @SuppressWarnings("unused") UserInterfaceModel model)
958        {
959 
960        }
961 
962        /**
963         * update a Reference List and ignore the updates that it might generate
964         * 
965         * @param selectionListID the selection list
966         * @param selectedObjectIDList the list of selected object IDs
967         * @param oldSelectedObjectIDList the previous selection
968         * @param callback function call back
969         */
970        public void updateReferenceList(
971                String selectionListID, ArrayList<String> selectedObjectIDList,
972                ArrayList<String> oldSelectedObjectIDList, AsyncCallback<Void> callback)
973        {
974                addIgnoreAddEvents(selectionListID, selectedObjectIDList,
975                        oldSelectedObjectIDList);
976 
977                addIgnoreRemoveEvents(selectionListID, selectedObjectIDList,
978                        oldSelectedObjectIDList);
979 
980                AsyncCallback<Void> callBackToUse =
981                        createUIRefreshLinkedCallback(callback);
982 
983                getUserInterfaceService().updateReferenceList(selectionListID,
984                        selectedObjectIDList, callBackToUse);
985        }
986 
987        /**
988         * create UI Refresh Linked Call back
989         * 
990         * @param <T> the type of value returned in the call
991         * @param originalCallback the original call back
992         * @return a call back that will invoke the original call back and trigger a
993         *         UI refresh.
994         */
995        public <T> AsyncCallback<T> createUIRefreshLinkedCallback(
996                AsyncCallback<T> originalCallback)
997        {
998                RefreshUiOnSuccessLinkedAsyncCallback<T> callbackToUse =
999                        new RefreshUiOnSuccessLinkedAsyncCallback<T>();
1000                callbackToUse.setLinkedCallback(originalCallback);
1001                return callbackToUse;
1002        }
1003 
1004        /**
1005         * add Ignore Remove Events
1006         * 
1007         * @param selectionListID the selection list ID
1008         * @param selectedObjectIDList the new list of selected IDs
1009         * @param oldSelectedObjectIDList the old list of selected IDs
1010         */
1011        public void addIgnoreRemoveEvents(
1012                String selectionListID, List<String> selectedObjectIDList,
1013                List<String> oldSelectedObjectIDList)
1014        {
1015                List<String> removeStrings = new ArrayList<String>();
1016 
1017                if (oldSelectedObjectIDList != null)
1018                {
1019                        removeStrings.addAll(oldSelectedObjectIDList);
1020                }
1021                if (selectedObjectIDList != null)
1022                {
1023                        removeStrings.removeAll(selectedObjectIDList);
1024                }
1025 
1026                for (String removeId : removeStrings)
1027                {
1028                        ChangeEvent ignoreEvent = new ChangeEvent();
1029                        ignoreEvent.setId(selectionListID);
1030                        ignoreEvent.setName("selected user interface element");
1031                        ignoreEvent.setType("remove");
1032                        ignoreEvent.setValue(Serializer.serializeString(removeId));
1033                        addEventToIgnoreList(ignoreEvent);
1034                }
1035        }
1036 
1037        /**
1038         * add Ignore Add Events
1039         * 
1040         * @param selectionListID the selection list ID
1041         * @param selectedObjectIDList the new selection list
1042         * @param oldSelectedObjectIDList the old selection list
1043         */
1044        public void addIgnoreAddEvents(
1045                String selectionListID, List<String> selectedObjectIDList,
1046                List<String> oldSelectedObjectIDList)
1047        {
1048                List<String> addStrings = new ArrayList<String>();
1049 
1050                if (selectedObjectIDList != null)
1051                {
1052                        addStrings.addAll(selectedObjectIDList);
1053                }
1054                if (oldSelectedObjectIDList != null)
1055                {
1056                        addStrings.removeAll(oldSelectedObjectIDList);
1057                }
1058 
1059                for (String addId : addStrings)
1060                {
1061                        ChangeEvent ignoreEvent = new ChangeEvent();
1062                        ignoreEvent.setId(selectionListID);
1063                        ignoreEvent.setName("selected user interface element");
1064                        ignoreEvent.setType("add");
1065                        ignoreEvent.setValue(Serializer.serializeString(addId));
1066                        addEventToIgnoreList(ignoreEvent);
1067                }
1068        }
1069 
1070}

[all classes][org.deduced.viewer.web.shared]
EMMA 2.0.9525 (unsupported private build) (C) Vladimir Roubtsov