@Override
 public void init(final Application application) {
   AnnotationEventDispatcherConfig config = new AnnotationEventDispatcherConfig();
   application.setMetaData(ANNOTATION_EVENT_DISPATCHER_CONFIG_CONTEXT_KEY, config);
   AnnotationEventDispatcher dispatcher = new AnnotationEventDispatcher();
   application.getComponentInstantiationListeners().add(dispatcher);
   application.getFrameworkSettings().add(dispatcher);
 }
 private static void touch(final Application application, String id) {
   id = getPageId(application, id);
   ConcurrentMap<String, Time> eventsTimeById;
   synchronized (application) {
     eventsTimeById = application.getMetaData(EVENTS_KEY);
     if (eventsTimeById == null) {
       eventsTimeById = new ConcurrentHashMap<String, Time>();
       application.setMetaData(EVENTS_KEY, eventsTimeById);
     }
   }
   eventsTimeById.put(id, Time.now());
 }
 /**
  * Methods used to access the triggers queued for the behavior
  *
  * <p>The implementation uses a Map stored in the application, where the behavior id is the key,
  * because these triggers cannot be stored in component instance or the behavior itself, since
  * they may be serialized and deserialized.
  *
  * @param application the application in which the triggers are stored
  * @param id the id of the behavior
  * @return a List of triggers queued for the component
  */
 private static List<DelayedMethodCallList> getTriggers(final Application application, String id) {
   id = getPageId(application, id);
   ConcurrentMap<String, List<DelayedMethodCallList>> triggersById;
   synchronized (application) {
     triggersById = application.getMetaData(TRIGGERS_KEY);
     if (triggersById == null) {
       triggersById = new ConcurrentHashMap<String, List<DelayedMethodCallList>>();
       application.setMetaData(TRIGGERS_KEY, triggersById);
     }
   }
   List<DelayedMethodCallList> triggers = triggersById.get(id);
   if (triggers == null) {
     triggersById.putIfAbsent(id, new ArrayList<DelayedMethodCallList>());
     triggers = triggersById.get(id);
   }
   return triggers;
 }
 private static void setRedirectId(
     final Application application, final String id, final String redirectedId) {
   ConcurrentMap<String, String> pageIdsById;
   synchronized (application) {
     pageIdsById = application.getMetaData(PAGE_ID_KEY);
     if (pageIdsById == null) {
       pageIdsById = new ConcurrentHashMap<String, String>();
       application.setMetaData(PAGE_ID_KEY, pageIdsById);
     }
   }
   final String oldRedirectedId = pageIdsById.put(id, redirectedId);
   if (!redirectedId.equals(oldRedirectedId)) {
     /*
      * The id was not already redirected to the redirectedId, we need to
      * merge the information before redirection with information after
      * redirection
      */
     final String idToRedirect = oldRedirectedId == null ? id : oldRedirectedId;
     redirect(application, idToRedirect, redirectedId);
   }
 }
 public RepeaterUtil(Application application) {
   this.application = application;
   application.setMetaData(REPEATER_UTIL_KEY, this);
 }