@Override
  public void prePassivate(ModuleMetaModel metaModel) {
    context.prePassivate();

    //
    for (ApplicationMetaModelPlugin plugin : context.getPlugins()) {
      plugin.prePassivate(metaModel);
    }

    //
    emitConfig(metaModel);
  }
  @Override
  public void postActivate(ModuleMetaModel metaModel) {
    for (ApplicationMetaModelPlugin plugin : context.getPlugins()) {
      plugin.postActivate(metaModel);
    }

    //
    context.postActivate(metaModel.processingContext);
    for (ApplicationMetaModel application : metaModel.getChildren(ApplicationMetaModel.class)) {
      for (ApplicationMetaModelPlugin plugin : context.getPlugins()) {
        plugin.postActivate(application);
      }
    }
  }
  @Override
  public Set<Class<? extends java.lang.annotation.Annotation>> init(ProcessingContext env) {

    //
    context.init(env);

    // We are interested by the Application annotation
    HashSet<Class<? extends java.lang.annotation.Annotation>> annotationTypes =
        new HashSet<Class<? extends java.lang.annotation.Annotation>>();
    annotationTypes.add(Application.class);
    annotationTypes.addAll(context.getSupportedAnnotations());

    //
    return annotationTypes;
  }
 private ApplicationMetaModel add(
     ModuleMetaModel metaModel, ElementHandle.Package handle, String applicationName) {
   ApplicationMetaModel application = new ApplicationMetaModel(handle, applicationName);
   metaModel.addChild(Key.of(handle, ApplicationMetaModel.class), application);
   context.add(application);
   return application;
 }
  @Override
  public void processAnnotationChanges(
      ModuleMetaModel metaModel, Iterable<AnnotationChange> changes) {

    // Normal processing for now
    super.processAnnotationChanges(metaModel, changes);

    // Forward
    context.processAnnotationChanges(changes);
  }
 @Override
 public void processAnnotationRemoved(
     ModuleMetaModel metaModel, AnnotationKey key, AnnotationState removed) {
   if (key.getType().equals(APPLICATION)) {
     ElementHandle.Package pkg = (ElementHandle.Package) key.getElement();
     ApplicationMetaModel mm = metaModel.getChild(Key.of(pkg, ApplicationMetaModel.class));
     if (mm != null) {
       context.remove(mm);
       mm.remove();
     }
   }
 }
  @Override
  public void postProcessAnnotations(ModuleMetaModel metaModel) {

    // Resolve applications
    for (ApplicationMetaModel application : metaModel.getChildren(ApplicationMetaModel.class)) {
      if (application.modified) {
        metaModel.queue(MetaModelEvent.createUpdated(application));
        application.modified = false;
      }
    }

    //
    context.postProcessAnnotations();
  }
  @Override
  public void processEvents(ModuleMetaModel metaModel, EventQueue queue) {
    // Handle root events
    while (queue.hasEvents()) {
      MetaModelEvent event = queue.popEvent();
      MetaModelObject obj = event.getObject();
      if (obj instanceof ApplicationMetaModel) {
        ApplicationMetaModel application = (ApplicationMetaModel) obj;
        if (event.getType() == MetaModelEvent.AFTER_ADD) {
          emitApplication(metaModel.processingContext, application);
        }
      }
    }

    // Distribute per application nevents
    context.processEvents();
  }
  private void emitConfig(ModuleMetaModel metaModel) {
    JSON descriptor = new JSON();

    // Application configs
    for (ApplicationMetaModel application : metaModel.getChildren(ApplicationMetaModel.class)) {

      //
      metaModel.processingContext.log(
          "Emitting application " + application.getHandle() + " config");

      // Recycle
      descriptor.clear();

      // Emit config
      for (ApplicationMetaModelPlugin plugin : context.getPlugins()) {
        JSON pluginDescriptor = plugin.getDescriptor(application);
        if (pluginDescriptor != null) {
          descriptor.set(plugin.getName(), pluginDescriptor);
        }
      }

      //
      Writer writer = null;
      try {
        FileObject fo =
            metaModel.processingContext.createResource(
                StandardLocation.CLASS_OUTPUT, application.getName(), "config.json");
        writer = fo.openWriter();
        descriptor.toString(writer, 2);
      } catch (IOException e) {
        throw ApplicationMetaModel.CANNOT_WRITE_APPLICATION_CONFIG.failure(
            e, metaModel.processingContext.get(application.getHandle()), application.getName());
      } finally {
        Tools.safeClose(writer);
      }
    }
  }
 @Override
 public void postProcessEvents(ModuleMetaModel metaModel) {
   context.postProcessEvents();
 }