Package org.jboss.errai.jpa.sync.rebind

Source Code of org.jboss.errai.jpa.sync.rebind.SyncDecorator

package org.jboss.errai.jpa.sync.rebind;

import static org.jboss.errai.codegen.meta.MetaClassFactory.parameterizedAs;
import static org.jboss.errai.codegen.meta.MetaClassFactory.typeParametersOf;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jboss.errai.codegen.Parameter;
import org.jboss.errai.codegen.Statement;
import org.jboss.errai.codegen.builder.AnonymousClassStructureBuilder;
import org.jboss.errai.codegen.builder.BlockBuilder;
import org.jboss.errai.codegen.exception.GenerationException;
import org.jboss.errai.codegen.meta.MetaClass;
import org.jboss.errai.codegen.meta.MetaClassFactory;
import org.jboss.errai.codegen.meta.MetaField;
import org.jboss.errai.codegen.meta.MetaMethod;
import org.jboss.errai.codegen.meta.MetaParameter;
import org.jboss.errai.codegen.util.GenUtil;
import org.jboss.errai.codegen.util.Refs;
import org.jboss.errai.codegen.util.Stmt;
import org.jboss.errai.ioc.client.api.CodeDecorator;
import org.jboss.errai.ioc.client.container.InitializationCallback;
import org.jboss.errai.ioc.rebind.ioc.extension.IOCDecoratorExtension;
import org.jboss.errai.ioc.rebind.ioc.injector.InjectUtil;
import org.jboss.errai.ioc.rebind.ioc.injector.api.InjectableInstance;
import org.jboss.errai.jpa.sync.client.local.ClientSyncWorker;
import org.jboss.errai.jpa.sync.client.local.DataSyncCallback;
import org.jboss.errai.jpa.sync.client.local.Sync;
import org.jboss.errai.jpa.sync.client.local.SyncParam;
import org.jboss.errai.jpa.sync.client.shared.SyncResponses;

/**
* Generates an {@link InitializationCallback} that contains data sync logic.
*
* @author Christian Sadilek <csadilek@redhat.com>
* @author Jonathan Fuerth <jfuerth@redhat.com>
*/
@CodeDecorator
public class SyncDecorator extends IOCDecoratorExtension<Sync> {

  public SyncDecorator(Class<Sync> decoratesWith) {
    super(decoratesWith);
  }

  @Override
  public List<? extends Statement> generateDecorator(InjectableInstance<Sync> ctx) {

    MetaMethod method = ctx.getMethod();
    MetaParameter[] params = method.getParameters();
    if (params.length != 1 || !params[0].getType().getErased().equals(MetaClassFactory.get(SyncResponses.class))) {
      throw new GenerationException("Methods annotated with @" + Sync.class.getName()
          + " need to have exactly one parameter of type: "
          + SyncResponses.class.getName() +
          ". Check method: "  + GenUtil.getMethodString(method) + " in class " + method.getDeclaringClass().getFullyQualifiedName());
    }
   
    final List<Statement> statements = new ArrayList<Statement>();

    Sync syncAnnotation = ctx.getAnnotation();
    statements.add(Stmt.declareFinalVariable("objectClass", Class.class, Stmt.loadLiteral(Object.class)));

    statements.add(Stmt.declareFinalVariable(
            "syncWorker",
            ClientSyncWorker.class,
            Stmt.invokeStatic(ClientSyncWorker.class, "create", syncAnnotation.query(),
                    Stmt.loadVariable("objectClass"), null)));

    statements.add(Stmt.loadVariable("syncWorker").invoke("addSyncCallback", createSyncCallback(ctx)));

    ctx.getTargetInjector().addStatementToEndOfInjector(
        Stmt.loadVariable("context").invoke("addInitializationCallback",
                  Refs.get(ctx.getInjector().getInstanceVarName()),
                  createInitCallback(ctx.getEnclosingType(), "obj", syncAnnotation, ctx)));

    Statement destruction = Stmt.loadVariable("syncWorker").invoke("stop");
    ctx.getTargetInjector().addStatementToEndOfInjector(
            Stmt.loadVariable("context").invoke(
                    "addDestructionCallback",
                    Refs.get(ctx.getInjector().getInstanceVarName()),
                    InjectUtil.createDestructionCallback(ctx.getEnclosingType(), "obj",
                            Collections.singletonList(destruction))));

    return statements;

  }

  /**
   * Generates an anonymous {@link DataSyncCallback} that will invoke the decorated sync method.
   */
  private Statement createSyncCallback(InjectableInstance<Sync> ctx) {
    return Stmt.newObject(DataSyncCallback.class)
            .extend()
            .publicOverridesMethod("onSync", Parameter.of(SyncResponses.class, "responses", true))
            .append(ctx.callOrBind(Stmt.loadVariable("responses")))
            .finish()
            .finish();
  }

  /**
   * Generates an anonymous {@link InitializationCallback} that will contain the logic to start the
   * {@link ClientSyncWorker}.
   */
  private Statement createInitCallback(final MetaClass type, final String initVar, final Sync syncAnnotation,
      final InjectableInstance<Sync> ctx) {

    BlockBuilder<AnonymousClassStructureBuilder> method =
        Stmt.newObject(parameterizedAs(InitializationCallback.class, typeParametersOf(type)))
            .extend()
            .publicOverridesMethod("init", Parameter.of(type, initVar, true));

    method.append(Stmt.declareFinalVariable("paramsMap", Map.class, Stmt.newObject(HashMap.class)));

    for (SyncParam param : syncAnnotation.params()) {
      Statement fieldValueStmt;
      String val = param.val().trim();
      if (val.startsWith("{") && val.endsWith("}")) {
        String fieldName = val.substring(1, val.length() - 1);
        MetaField field = ctx.getEnclosingType().getField(fieldName);
        fieldValueStmt =
            InjectUtil.getPublicOrPrivateFieldValue(ctx.getInjectionContext(), Stmt.loadVariable(ctx.getInjector()
                .getInstanceVarName()), field);
      }
      else {
        fieldValueStmt = Stmt.loadLiteral(val);
      }
      method.append(Stmt.loadVariable("paramsMap").invoke("put", param.name(), fieldValueStmt));
    }

    return method
        .append(Stmt.loadVariable("syncWorker").invoke("start", Stmt.loadVariable("paramsMap")))
        .finish()
        .finish();
  }

}
TOP

Related Classes of org.jboss.errai.jpa.sync.rebind.SyncDecorator

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.