@Override
  public OperatorMethodDescriptor describe(Context context) {
    Precondition.checkMustNotBeNull(context, "context"); // $NON-NLS-1$

    ExecutableAnalyzer a = new ExecutableAnalyzer(context.environment, context.element);
    if (a.isGeneric()) {
      a.error("単純集計演算子はジェネリックメソッドで宣言できません");
    }
    if (a.isAbstract() == false) {
      a.error("単純集計演算子はabstractで宣言する必要があります");
    }
    TypeConstraint summarized = a.getReturnType();
    if (summarized.isConcreteModel() == false) {
      a.error("単純集計演算子は戻り値にモデルオブジェクト型を指定する必要があります");
    }
    TypeConstraint summarizee = a.getParameterType(0);
    if (summarizee.isModel() == false) {
      a.error(0, "単純集計演算子の最初の引数はモデルオブジェクト型である必要があります");
    }
    for (int i = 1, n = a.countParameters(); i < n; i++) {
      a.error(i, "単純集計演算子にはユーザー引数を利用できません");
    }
    if (a.hasError()) {
      return null;
    }
    if (summarized.isSummarizedModel(summarizee.getType()) == false) {
      a.error("単純集計演算子の戻り値型は最初の引数の集計結果を表す型である必要があります");
      return null;
    }

    ShuffleKey key = summarized.getSummarizeKey();
    Summarize annotation = context.element.getAnnotation(Summarize.class);
    if (annotation == null) {
      a.error("注釈の解釈に失敗しました");
      return null;
    }
    OperatorProcessorUtil.checkPortName(
        a,
        new String[] {
          annotation.summarizedPort(),
        });
    if (a.hasError()) {
      return null;
    }

    Builder builder = new Builder(getTargetAnnotationType(), context);
    builder.addAttribute(FlowBoundary.SHUFFLE);
    builder.addAttribute(a.getObservationCount());
    builder.addAttribute(annotation.partialAggregation());
    builder.setDocumentation(a.getExecutableDocument());
    builder.addInput(
        a.getParameterDocument(0), a.getParameterName(0), a.getParameterType(0).getType(), 0, key);
    builder.addOutput(
        a.getReturnDocument(),
        annotation.summarizedPort(),
        a.getReturnType().getType(),
        null,
        null);
    return builder.toDescriptor();
  }