Использование генерации кода для создания похожих классов Java Action

Я создаю приложение с графическим интерфейсом в Java, используя платформу приложений (Netbeans Platform), которая требует большого количества почти идентичных классов для реализации чрезвычайно похожих Action классы. Я потратил много времени, пытаясь сгенерировать эти действия программно. Несмотря на то, что я могу генерировать действия, платформа использует аннотации во время компиляции для генерации других файлов внутреннего кэша / данных, которые мне не удалось воспроизвести с помощью программного подхода.

Мне интересно, являются ли инструменты генерации кода лучшим решением, или, возможно, некоторые пользовательские аннотации, которые обертывают аннотации платформы. Возможно что-то вроде Lombokили, может быть, плагин Maven. Но не знаю, с чего начать, и я не уверен, что это даже хороший путь для изучения. В идеале, я думаю, было бы здорово определить действия в файле данных и сгенерировать Java-код во время компиляции.

Проект с открытым исходным кодом, а также ряд других действий на github. Вот пример того, как может выглядеть шаблон: части, которые мне нужно добавить, заменены на {{string}}, {{code}} а также {{int}}:

// imports omitted

@ActionID(
        category = {{string}},
        id = {{string}})
@ActionRegistration(
        iconBase = {{string}},
        displayName = "resources.MessagesBundle#" + {{string}},
        lazy = false)
@ActionReferences({
        @ActionReference(
                path = {{string}},
                position = {{int}})
})
public final class {{string}} extends AbstractAction implements UGSEventListener {

    public static final String ICON_BASE = {{string}};

    private BackendAPI backend;

    public SoftResetAction() {
        this.backend = CentralLookup.getDefault().lookup(BackendAPI.class);
        this.backend.addUGSEventListener(this);

        putValue("iconBase", ICON_BASE);
        putValue(SMALL_ICON, ImageUtilities.loadImageIcon(ICON_BASE, false));
        putValue("menuText", {{string}});
        putValue(NAME, {{string}});

    }

    @Override
    public void UGSEvent(UGSEvent cse) {
        java.awt.EventQueue.invokeLater(() -> setEnabled(isEnabled()));
    }

    @Override
    public boolean isEnabled() {
        {{code}}
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        {{code}}
    }
}

2 ответа

Вы должны попробовать генератор кода, такой как Telosys ( http://www.telosys.org/)

Этот инструмент предназначен для такой ситуации, вам просто нужно создать шаблон для каждого типа повторяющегося класса и запустить генерацию.

Для получения дополнительной информации см. Принципы шаблонов: http://www.telosys.org/templates.html

Все бесплатно и с открытым исходным кодом, так что вы можете повторно использовать существующие шаблоны и адаптировать их в соответствии с вашими потребностями.

Несколько интересных постов об этом инструменте:

Вы можете создать общедоступный класс Action для обычного использования, как удар. Это только часть примера кода. Если у некоторых модулей есть свой собственный логический бизнес, вы можете реализовать этот PubAction для любого подкласса.

import java.awt.event.ActionEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.AbstractAction;


public abstract class PubAction
  extends AbstractAction
  implements AppEventListener
{
  protected ActionInterceptor interceptor;
  protected IExceptionHandler exceptionHandler;
  protected IActionStatusJudge actionStatusJudge = null;

  public static final String TOOLBAR_SHOWNAME_KEY = "TOOLBAR_SHOWNAME_KEY";

  public PubAction()
  {
    setShowNameInToolbar(false);
  }

  public String getBtnName() {
    return (String)getValue("Name");
  }

  public void setBtnName(String btnName) {
    putValue("Name", btnName);
  }

  public void setCode(String code)
  {
    putValue("Code", code);
  }

  public void handleEvent(AppEvent event)
  {
    updateStatus();
  }

  public void updateStatus()
  {
    boolean isEnable = isActionEnable();
    setEnabled(getActionStatusJudge() == null ? isEnable : getActionStatusJudge().isActionEnable(this, isEnable));
  }

  protected boolean isActionEnable() {
    return true;
  }

  public void setShowNameInToolbar(boolean isShow)
  {
    putValue("TOOLBAR_SHOWNAME_KEY", isShow ? Boolean.TRUE : Boolean.FALSE);
  }

  public void actionPerformed(ActionEvent e) {
    Logger.debug("Entering " + getClass().toString() + ".actionPerformed");
    beforeDoAction();
    try
    {
      if ((interceptor == null) || (interceptor.beforeDoAction(this, e)))
      {
        try
        {
          doAction(e);
          if (interceptor != null) {
            interceptor.afterDoActionSuccessed(this, e);
          }
        } catch (Exception ex) {
          if ((interceptor == null) || (interceptor.afterDoActionFailed(this, e, ex)))
          {
            if (getExceptionHandler() != null)
            {
              processExceptionHandler(ex);
            }
            else if ((ex instanceof RuntimeException))
            {
              throw ((RuntimeException)ex);
            }

            throw new RuntimeException(ex);
          }
        }
      }
    }
    finally
    {
      Logger.debug("Leaving " + getClass().toString() + ".actionPerformed");
    }
  }



  protected void processExceptionHandler(Exception ex)
  {
    new ExceptionHandlerUtil().processErrorMsg4SpecialAction(this, getExceptionHandler(), ex);
  }

  protected void beforeDoAction()
  {
    Method[] ms = getClass().getMethods();
    for (Method m : ms)
    {
      Class<?> clazz = m.getReturnType();
      if (AbstractUIAppModel.class.isAssignableFrom(clazz)) {
        try
        {
          AbstractUIAppModel model = (AbstractUIAppModel)m.invoke(this, null);
          if (model == null)
            return;
          LoginContext ctx = model.getContext();
          if (ctx == null)
            break;
          ShowStatusBarMsgUtil.showStatusBarMsg("", ctx);
        } catch (IllegalArgumentException e) {
          Logger.debug(e.getMessage());
        } catch (IllegalAccessException e) {
          Logger.debug(e.getMessage());
        } catch (InvocationTargetException e) {
          Logger.debug(e.getMessage());
        }
      }
    }
  }

  public abstract void doAction(ActionEvent paramActionEvent) throws Exception;

  public ActionInterceptor getInterceptor()
  {
    return interceptor;
  }

  public void setInterceptor(ActionInterceptor interceptor) {
    this.interceptor = interceptor;
  }

  public IExceptionHandler getExceptionHandler() {
    return exceptionHandler;
  }

  public void setExceptionHandler(IExceptionHandler exceptionHandler) {
    this.exceptionHandler = exceptionHandler;
  }

  public IActionStatusJudge getActionStatusJudge() {
    return actionStatusJudge;
  }

  public void setActionStatusJudge(IActionStatusJudge actionStatusJudge) {
    this.actionStatusJudge = actionStatusJudge;
  }
}
Другие вопросы по тегам