Package juzu.impl.plugin.application.metamodel

Source Code of juzu.impl.plugin.application.metamodel.ApplicationModuleMetaModelPlugin

/*
* Copyright 2013 eXo Platform SAS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package juzu.impl.plugin.application.metamodel;

import juzu.Application;
import juzu.impl.common.Name;
import juzu.impl.plugin.application.descriptor.ApplicationDescriptor;
import juzu.impl.common.JSON;
import juzu.impl.common.Tools;
import juzu.impl.compiler.ElementHandle;
import juzu.impl.compiler.ProcessingException;
import juzu.impl.metamodel.AnnotationChange;
import juzu.impl.metamodel.AnnotationKey;
import juzu.impl.metamodel.AnnotationState;
import juzu.impl.compiler.ProcessingContext;
import juzu.impl.metamodel.EventQueue;
import juzu.impl.metamodel.Key;
import juzu.impl.metamodel.MetaModelContext;
import juzu.impl.metamodel.MetaModelEvent;
import juzu.impl.metamodel.MetaModelObject;
import juzu.impl.plugin.module.metamodel.ModuleMetaModel;
import juzu.impl.plugin.module.metamodel.ModuleMetaModelPlugin;
import juzu.impl.plugin.template.metamodel.TemplateMetaModel;

import javax.annotation.processing.Completion;
import javax.lang.model.element.PackageElement;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public class ApplicationModuleMetaModelPlugin extends ModuleMetaModelPlugin {

  /** . */
  private static final Name APPLICATION = Name.create(Application.class);

  /** . */
  private static final String APPLICATION_DESCRIPTOR = ApplicationDescriptor.class.getSimpleName();

  /** . */
  final MetaModelContext<ApplicationMetaModelPlugin, ApplicationMetaModel> context;

  public ApplicationModuleMetaModelPlugin() {
    super("application");

    //
    this.context = new MetaModelContext<ApplicationMetaModelPlugin, ApplicationMetaModel>(ApplicationMetaModelPlugin.class);
  }

  @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;
  }

  @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 void processAnnotationChange(ModuleMetaModel metaModel, AnnotationChange change) {

    // Normal processing for now
    super.processAnnotationChange(metaModel, change);

    // Forward
    context.processAnnotationChange(change);
  }

  @Override
  public Iterable<? extends Completion> getCompletions(
      ModuleMetaModel metaModel,
      AnnotationKey annotationKey,
      AnnotationState annotationState,
      String member,
      String userText) {
    Iterable<? extends Completion> completions = super.getCompletions(metaModel, annotationKey, annotationState, member, userText);

    // Forward
    if (completions == null) {
      completions = context.getCompletions(annotationKey, annotationState, member, userText);
    }

    //
    return completions;
  }

  @Override
  public void processAnnotationAdded(ModuleMetaModel metaModel, AnnotationKey key, AnnotationState added) {
    if (key.getType().equals(APPLICATION)) {
      ElementHandle.Package pkg = (ElementHandle.Package)key.getElement();
      String name = (String)added.get("name");
      ApplicationMetaModel application = new ApplicationMetaModel(pkg, name);
      metaModel.addChild(Key.of(pkg, ApplicationMetaModel.class), application);
      context.add(application);
    }
  }

  @Override
  public void processAnnotationUpdated(ModuleMetaModel metaModel, AnnotationKey key, AnnotationState removed, AnnotationState added) {
    if (key.getType().equals(APPLICATION)) {
      ElementHandle.Package pkg = (ElementHandle.Package)key.getElement();
      ApplicationMetaModel application = metaModel.getChild(Key.of(pkg, ApplicationMetaModel.class));
      application.modified = true;
    }
  }

  @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();
  }

  void emitApplication(ProcessingContext env, ApplicationMetaModel application) throws ProcessingException {
    PackageElement elt = env.get(application.getHandle());
    Name fqn = application.getName().append("Application");

    //
    Writer writer = null;
    try {
      JavaFileObject applicationFile = env.createSourceFile(fqn, elt);
      writer = applicationFile.openWriter();

      writer.append("package ").append(fqn.getParent()).append(";\n");

      // Imports
      writer.append("import ").append(ApplicationDescriptor.class.getCanonicalName()).append(";\n");

      // Open class
      writer.append("public class ").append(fqn.getIdentifier()).append(" {\n");

      // Field
      writer.append("private final ").append(APPLICATION_DESCRIPTOR).append(" descriptor;\n");

      // Constructor
      writer.append("public ").append(fqn.getIdentifier()).append("() throws Exception {\n");
      writer.append("this.descriptor = ").append(APPLICATION_DESCRIPTOR).append(".create(getClass());\n");
      writer.append("}\n");

      // Getter
      writer.append("public ").append(APPLICATION_DESCRIPTOR).append(" getDescriptor() {\n");
      writer.append("return descriptor;\n");
      writer.append("}\n");

      // Close class
      writer.append("}\n");

      //
      env.info("Generated application " + fqn + " as " + applicationFile.toUri());
    }
    catch (IOException e) {
      throw TemplateMetaModel.CANNOT_WRITE_APPLICATION.failure(e, elt, application.getName());
    }
    finally {
      Tools.safeClose(writer);
    }
  }

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

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

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

    //
    emitConfig(metaModel);
  }

  private void emitConfig(ModuleMetaModel metaModel) {
    // Application configs
    Collection<ApplicationMetaModel> applications = metaModel.getChildren(ApplicationMetaModel.class);
    if (applications != null && applications.size() > 0) {
      for (ApplicationMetaModel application : applications) {

        //
        JSON descriptor = new JSON();
        metaModel.processingContext.info("Emitting application " + application.getHandle() + " config");

        // 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 JSON getDescriptor(ModuleMetaModel metaModel) {
    JSON json = null;
    Collection<ApplicationMetaModel> applications = metaModel.getChildren(ApplicationMetaModel.class);
    if (applications != null && applications.size() > 0) {
      json = new JSON();
      for (ApplicationMetaModel application : applications) {
        json.set(application.getHandle().getPackageName().toString(), new JSON());
      }
    }
    return json;
  }
}
TOP

Related Classes of juzu.impl.plugin.application.metamodel.ApplicationModuleMetaModelPlugin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.