/* This file was generated by SableCC's ObjectMacro. */

package org.sablecc.objectmacro.codegeneration.java.macro;

import java.util.*;

public class MMacroBuilder
        extends Macro {

    private DSeparator ContextParamSeparator;

    private DBeforeFirst ContextParamBeforeFirst;

    private DAfterLast ContextParamAfterLast;

    private DNone ContextParamNone;

    final List<Macro> list_ContextParam;

    final Context ContextParamContext = new Context();

    final MacroValue ContextParamValue;

    private DSeparator ContextCacheBuilderSeparator;

    private DBeforeFirst ContextCacheBuilderBeforeFirst;

    private DAfterLast ContextCacheBuilderAfterLast;

    private DNone ContextCacheBuilderNone;

    final List<Macro> list_ContextCacheBuilder;

    final Context ContextCacheBuilderContext = new Context();

    final MacroValue ContextCacheBuilderValue;

    private DSeparator NewCacheBuilderSeparator;

    private DBeforeFirst NewCacheBuilderBeforeFirst;

    private DAfterLast NewCacheBuilderAfterLast;

    private DNone NewCacheBuilderNone;

    final List<Macro> list_NewCacheBuilder;

    final Context NewCacheBuilderContext = new Context();

    final MacroValue NewCacheBuilderValue;

    private DSeparator DirectivesCallsSeparator;

    private DBeforeFirst DirectivesCallsBeforeFirst;

    private DAfterLast DirectivesCallsAfterLast;

    private DNone DirectivesCallsNone;

    final List<Macro> list_DirectivesCalls;

    final Context DirectivesCallsContext = new Context();

    final MacroValue DirectivesCallsValue;

    private DSeparator InternalsCallsSeparator;

    private DBeforeFirst InternalsCallsBeforeFirst;

    private DAfterLast InternalsCallsAfterLast;

    private DNone InternalsCallsNone;

    final List<Macro> list_InternalsCalls;

    final Context InternalsCallsContext = new Context();

    final MacroValue InternalsCallsValue;

    private DSeparator MacroBodyPartsSeparator;

    private DBeforeFirst MacroBodyPartsBeforeFirst;

    private DAfterLast MacroBodyPartsAfterLast;

    private DNone MacroBodyPartsNone;

    final List<Macro> list_MacroBodyParts;

    final Context MacroBodyPartsContext = new Context();

    final MacroValue MacroBodyPartsValue;

    private DSeparator PublicSeparator;

    private DBeforeFirst PublicBeforeFirst;

    private DAfterLast PublicAfterLast;

    private DNone PublicNone;

    final List<Macro> list_Public;

    final Context PublicContext = new Context();

    final MacroValue PublicValue;

    private DSeparator OverrideSeparator;

    private DBeforeFirst OverrideBeforeFirst;

    private DAfterLast OverrideAfterLast;

    private DNone OverrideNone;

    final List<Macro> list_Override;

    final Context OverrideContext = new Context();

    final MacroValue OverrideValue;

    MMacroBuilder(
            Macros macros) {

        setMacros(macros);
        this.list_ContextParam = new LinkedList<>();
        this.list_ContextCacheBuilder = new LinkedList<>();
        this.list_NewCacheBuilder = new LinkedList<>();
        this.list_DirectivesCalls = new LinkedList<>();
        this.list_InternalsCalls = new LinkedList<>();
        this.list_MacroBodyParts = new LinkedList<>();
        this.list_Public = new LinkedList<>();
        this.list_Override = new LinkedList<>();

        this.ContextParamValue = new MacroValue(this.list_ContextParam,
                this.ContextParamContext);
        this.ContextCacheBuilderValue = new MacroValue(
                this.list_ContextCacheBuilder, this.ContextCacheBuilderContext);
        this.NewCacheBuilderValue = new MacroValue(this.list_NewCacheBuilder,
                this.NewCacheBuilderContext);
        this.DirectivesCallsValue = new MacroValue(this.list_DirectivesCalls,
                this.DirectivesCallsContext);
        this.InternalsCallsValue = new MacroValue(this.list_InternalsCalls,
                this.InternalsCallsContext);
        this.MacroBodyPartsValue = new MacroValue(this.list_MacroBodyParts,
                this.MacroBodyPartsContext);
        this.PublicValue = new MacroValue(this.list_Public, this.PublicContext);
        this.OverrideValue
                = new MacroValue(this.list_Override, this.OverrideContext);
    }

    MMacroBuilder(
            List<Macro> pContextParam,
            List<Macro> pContextCacheBuilder,
            List<Macro> pNewCacheBuilder,
            List<Macro> pDirectivesCalls,
            List<Macro> pInternalsCalls,
            List<Macro> pMacroBodyParts,
            List<Macro> pPublic,
            List<Macro> pOverride,
            Macros macros) {

        setMacros(macros);
        this.list_ContextParam = new LinkedList<>();
        this.list_ContextCacheBuilder = new LinkedList<>();
        this.list_NewCacheBuilder = new LinkedList<>();
        this.list_DirectivesCalls = new LinkedList<>();
        this.list_InternalsCalls = new LinkedList<>();
        this.list_MacroBodyParts = new LinkedList<>();
        this.list_Public = new LinkedList<>();
        this.list_Override = new LinkedList<>();

        this.ContextParamValue = new MacroValue(this.list_ContextParam,
                this.ContextParamContext);
        this.ContextCacheBuilderValue = new MacroValue(
                this.list_ContextCacheBuilder, this.ContextCacheBuilderContext);
        this.NewCacheBuilderValue = new MacroValue(this.list_NewCacheBuilder,
                this.NewCacheBuilderContext);
        this.DirectivesCallsValue = new MacroValue(this.list_DirectivesCalls,
                this.DirectivesCallsContext);
        this.InternalsCallsValue = new MacroValue(this.list_InternalsCalls,
                this.InternalsCallsContext);
        this.MacroBodyPartsValue = new MacroValue(this.list_MacroBodyParts,
                this.MacroBodyPartsContext);
        this.PublicValue = new MacroValue(this.list_Public, this.PublicContext);
        this.OverrideValue
                = new MacroValue(this.list_Override, this.OverrideContext);
        if (pContextParam != null) {
            addAllContextParam(pContextParam);
        }
        if (pContextCacheBuilder != null) {
            addAllContextCacheBuilder(pContextCacheBuilder);
        }
        if (pNewCacheBuilder != null) {
            addAllNewCacheBuilder(pNewCacheBuilder);
        }
        if (pDirectivesCalls != null) {
            addAllDirectivesCalls(pDirectivesCalls);
        }
        if (pInternalsCalls != null) {
            addAllInternalsCalls(pInternalsCalls);
        }
        if (pMacroBodyParts != null) {
            addAllMacroBodyParts(pMacroBodyParts);
        }
        if (pPublic != null) {
            addAllPublic(pPublic);
        }
        if (pOverride != null) {
            addAllOverride(pOverride);
        }
    }

    public void addAllContextParam(
            List<Macro> macros) {

        if (macros == null) {
            throw ObjectMacroException.parameterNull("ContextParam");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        int i = 0;

        for (Macro macro : macros) {
            if (macro == null) {
                throw ObjectMacroException.macroNull(i, "ContextParam");
            }

            if (getMacros() != macro.getMacros()) {
                throw ObjectMacroException.diffMacros();
            }

            verifyTypeContextParam(macro);
            this.list_ContextParam.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypeContextParam(
            Macro macro) {

        macro.apply(new InternalsInitializer("ContextParam") {

            @Override
            void setContextParam(
                    MContextParam mContextParam) {

            }
        });
    }

    public void addContextParam(
            MContextParam macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("ContextParam");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_ContextParam.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addAllContextCacheBuilder(
            List<Macro> macros) {

        if (macros == null) {
            throw ObjectMacroException.parameterNull("ContextCacheBuilder");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        int i = 0;

        for (Macro macro : macros) {
            if (macro == null) {
                throw ObjectMacroException.macroNull(i, "ContextCacheBuilder");
            }

            if (getMacros() != macro.getMacros()) {
                throw ObjectMacroException.diffMacros();
            }

            verifyTypeContextCacheBuilder(macro);
            this.list_ContextCacheBuilder.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypeContextCacheBuilder(
            Macro macro) {

        macro.apply(new InternalsInitializer("ContextCacheBuilder") {

            @Override
            void setContextCacheBuilder(
                    MContextCacheBuilder mContextCacheBuilder) {

            }
        });
    }

    public void addContextCacheBuilder(
            MContextCacheBuilder macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("ContextCacheBuilder");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_ContextCacheBuilder.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addAllNewCacheBuilder(
            List<Macro> macros) {

        if (macros == null) {
            throw ObjectMacroException.parameterNull("NewCacheBuilder");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        int i = 0;

        for (Macro macro : macros) {
            if (macro == null) {
                throw ObjectMacroException.macroNull(i, "NewCacheBuilder");
            }

            if (getMacros() != macro.getMacros()) {
                throw ObjectMacroException.diffMacros();
            }

            verifyTypeNewCacheBuilder(macro);
            this.list_NewCacheBuilder.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypeNewCacheBuilder(
            Macro macro) {

        macro.apply(new InternalsInitializer("NewCacheBuilder") {

            @Override
            void setNewCacheBuilder(
                    MNewCacheBuilder mNewCacheBuilder) {

            }
        });
    }

    public void addNewCacheBuilder(
            MNewCacheBuilder macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("NewCacheBuilder");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_NewCacheBuilder.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addAllDirectivesCalls(
            List<Macro> macros) {

        if (macros == null) {
            throw ObjectMacroException.parameterNull("DirectivesCalls");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        int i = 0;

        for (Macro macro : macros) {
            if (macro == null) {
                throw ObjectMacroException.macroNull(i, "DirectivesCalls");
            }

            if (getMacros() != macro.getMacros()) {
                throw ObjectMacroException.diffMacros();
            }

            verifyTypeDirectivesCalls(macro);
            this.list_DirectivesCalls.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypeDirectivesCalls(
            Macro macro) {

        macro.apply(new InternalsInitializer("DirectivesCalls") {

            @Override
            void setInitDirectiveCall(
                    MInitDirectiveCall mInitDirectiveCall) {

            }
        });
    }

    public void addDirectivesCalls(
            MInitDirectiveCall macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("DirectivesCalls");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_DirectivesCalls.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addAllInternalsCalls(
            List<Macro> macros) {

        if (macros == null) {
            throw ObjectMacroException.parameterNull("InternalsCalls");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        int i = 0;

        for (Macro macro : macros) {
            if (macro == null) {
                throw ObjectMacroException.macroNull(i, "InternalsCalls");
            }

            if (getMacros() != macro.getMacros()) {
                throw ObjectMacroException.diffMacros();
            }

            verifyTypeInternalsCalls(macro);
            this.list_InternalsCalls.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypeInternalsCalls(
            Macro macro) {

        macro.apply(new InternalsInitializer("InternalsCalls") {

            @Override
            void setInitInternalsCall(
                    MInitInternalsCall mInitInternalsCall) {

            }
        });
    }

    public void addInternalsCalls(
            MInitInternalsCall macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("InternalsCalls");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_InternalsCalls.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addAllMacroBodyParts(
            List<Macro> macros) {

        if (macros == null) {
            throw ObjectMacroException.parameterNull("MacroBodyParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        int i = 0;

        for (Macro macro : macros) {
            if (macro == null) {
                throw ObjectMacroException.macroNull(i, "MacroBodyParts");
            }

            if (getMacros() != macro.getMacros()) {
                throw ObjectMacroException.diffMacros();
            }

            verifyTypeMacroBodyParts(macro);
            this.list_MacroBodyParts.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypeMacroBodyParts(
            Macro macro) {

        macro.apply(new InternalsInitializer("MacroBodyParts") {

            @Override
            void setInitStringBuilder(
                    MInitStringBuilder mInitStringBuilder) {

            }

            @Override
            void setStringPart(
                    MStringPart mStringPart) {

            }

            @Override
            void setParamInsertPart(
                    MParamInsertPart mParamInsertPart) {

            }

            @Override
            void setEolPart(
                    MEolPart mEolPart) {

            }

            @Override
            void setInsertMacroPart(
                    MInsertMacroPart mInsertMacroPart) {

            }

            @Override
            void setAddIndent(
                    MAddIndent mAddIndent) {

            }

            @Override
            void setIndentPart(
                    MIndentPart mIndentPart) {

            }
        });
    }

    public void addMacroBodyParts(
            MInitStringBuilder macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("MacroBodyParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_MacroBodyParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addMacroBodyParts(
            MStringPart macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("MacroBodyParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_MacroBodyParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addMacroBodyParts(
            MParamInsertPart macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("MacroBodyParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_MacroBodyParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addMacroBodyParts(
            MEolPart macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("MacroBodyParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_MacroBodyParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addMacroBodyParts(
            MInsertMacroPart macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("MacroBodyParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_MacroBodyParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addMacroBodyParts(
            MAddIndent macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("MacroBodyParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_MacroBodyParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addMacroBodyParts(
            MIndentPart macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("MacroBodyParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_MacroBodyParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addAllPublic(
            List<Macro> macros) {

        if (macros == null) {
            throw ObjectMacroException.parameterNull("Public");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        int i = 0;

        for (Macro macro : macros) {
            if (macro == null) {
                throw ObjectMacroException.macroNull(i, "Public");
            }

            if (getMacros() != macro.getMacros()) {
                throw ObjectMacroException.diffMacros();
            }

            verifyTypePublic(macro);
            this.list_Public.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypePublic(
            Macro macro) {

        macro.apply(new InternalsInitializer("Public") {

            @Override
            void setPublic(
                    MPublic mPublic) {

            }
        });
    }

    public void addPublic(
            MPublic macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("Public");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_Public.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addAllOverride(
            List<Macro> macros) {

        if (macros == null) {
            throw ObjectMacroException.parameterNull("Override");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        int i = 0;

        for (Macro macro : macros) {
            if (macro == null) {
                throw ObjectMacroException.macroNull(i, "Override");
            }

            if (getMacros() != macro.getMacros()) {
                throw ObjectMacroException.diffMacros();
            }

            verifyTypeOverride(macro);
            this.list_Override.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypeOverride(
            Macro macro) {

        macro.apply(new InternalsInitializer("Override") {

            @Override
            void setOverride(
                    MOverride mOverride) {

            }
        });
    }

    public void addOverride(
            MOverride macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("Override");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_Override.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    private String buildContextParam() {

        StringBuilder sb = new StringBuilder();
        Context local_context = this.ContextParamContext;
        List<Macro> macros = this.list_ContextParam;

        int i = 0;
        int nb_macros = macros.size();
        String expansion = null;

        for (Macro macro : macros) {
            expansion = macro.build(local_context);

            sb.append(expansion);
            i++;
        }

        return sb.toString();
    }

    private String buildContextCacheBuilder() {

        StringBuilder sb = new StringBuilder();
        Context local_context = this.ContextCacheBuilderContext;
        List<Macro> macros = this.list_ContextCacheBuilder;

        int i = 0;
        int nb_macros = macros.size();
        String expansion = null;

        if (this.ContextCacheBuilderNone == null) {
            initContextCacheBuilderDirectives();
        }

        sb.append(this.ContextCacheBuilderNone.apply(i, "", nb_macros));
        for (Macro macro : macros) {
            expansion = macro.build(local_context);

            sb.append(expansion);
            i++;
        }

        return sb.toString();
    }

    private String buildNewCacheBuilder() {

        StringBuilder sb = new StringBuilder();
        Context local_context = this.NewCacheBuilderContext;
        List<Macro> macros = this.list_NewCacheBuilder;

        int i = 0;
        int nb_macros = macros.size();
        String expansion = null;

        if (this.NewCacheBuilderNone == null
                || this.NewCacheBuilderBeforeFirst == null) {
            initNewCacheBuilderDirectives();
        }

        sb.append(this.NewCacheBuilderNone.apply(i, "", nb_macros));
        for (Macro macro : macros) {
            expansion = macro.build(local_context);

            expansion = this.NewCacheBuilderBeforeFirst.apply(i, expansion,
                    nb_macros);
            sb.append(expansion);
            i++;
        }

        return sb.toString();
    }

    private String buildDirectivesCalls() {

        StringBuilder sb = new StringBuilder();
        Context local_context = this.DirectivesCallsContext;
        List<Macro> macros = this.list_DirectivesCalls;

        int i = 0;
        int nb_macros = macros.size();
        String expansion = null;

        if (this.DirectivesCallsSeparator == null
                || this.DirectivesCallsBeforeFirst == null
                || this.DirectivesCallsAfterLast == null) {
            initDirectivesCallsDirectives();
        }

        for (Macro macro : macros) {
            expansion = macro.build(local_context);

            expansion = this.DirectivesCallsSeparator.apply(i, expansion,
                    nb_macros);
            expansion = this.DirectivesCallsBeforeFirst.apply(i, expansion,
                    nb_macros);
            expansion = this.DirectivesCallsAfterLast.apply(i, expansion,
                    nb_macros);
            sb.append(expansion);
            i++;
        }

        return sb.toString();
    }

    private String buildInternalsCalls() {

        StringBuilder sb = new StringBuilder();
        Context local_context = this.InternalsCallsContext;
        List<Macro> macros = this.list_InternalsCalls;

        int i = 0;
        int nb_macros = macros.size();
        String expansion = null;

        if (this.InternalsCallsSeparator == null
                || this.InternalsCallsBeforeFirst == null
                || this.InternalsCallsAfterLast == null) {
            initInternalsCallsDirectives();
        }

        for (Macro macro : macros) {
            expansion = macro.build(local_context);

            expansion = this.InternalsCallsSeparator.apply(i, expansion,
                    nb_macros);
            expansion = this.InternalsCallsBeforeFirst.apply(i, expansion,
                    nb_macros);
            expansion = this.InternalsCallsAfterLast.apply(i, expansion,
                    nb_macros);
            sb.append(expansion);
            i++;
        }

        return sb.toString();
    }

    private String buildMacroBodyParts() {

        StringBuilder sb = new StringBuilder();
        Context local_context = this.MacroBodyPartsContext;
        List<Macro> macros = this.list_MacroBodyParts;

        int i = 0;
        int nb_macros = macros.size();
        String expansion = null;

        if (this.MacroBodyPartsSeparator == null
                || this.MacroBodyPartsBeforeFirst == null
                || this.MacroBodyPartsAfterLast == null) {
            initMacroBodyPartsDirectives();
        }

        for (Macro macro : macros) {
            expansion = macro.build(local_context);

            expansion = this.MacroBodyPartsSeparator.apply(i, expansion,
                    nb_macros);
            expansion = this.MacroBodyPartsBeforeFirst.apply(i, expansion,
                    nb_macros);
            expansion = this.MacroBodyPartsAfterLast.apply(i, expansion,
                    nb_macros);
            sb.append(expansion);
            i++;
        }

        return sb.toString();
    }

    private String buildPublic() {

        StringBuilder sb = new StringBuilder();
        Context local_context = this.PublicContext;
        List<Macro> macros = this.list_Public;

        int i = 0;
        int nb_macros = macros.size();
        String expansion = null;

        if (this.PublicAfterLast == null) {
            initPublicDirectives();
        }

        for (Macro macro : macros) {
            expansion = macro.build(local_context);

            expansion = this.PublicAfterLast.apply(i, expansion, nb_macros);
            sb.append(expansion);
            i++;
        }

        return sb.toString();
    }

    private String buildOverride() {

        StringBuilder sb = new StringBuilder();
        Context local_context = this.OverrideContext;
        List<Macro> macros = this.list_Override;

        int i = 0;
        int nb_macros = macros.size();
        String expansion = null;

        for (Macro macro : macros) {
            expansion = macro.build(local_context);

            sb.append(expansion);
            i++;
        }

        return sb.toString();
    }

    MacroValue getContextParam() {

        return this.ContextParamValue;
    }

    MacroValue getContextCacheBuilder() {

        return this.ContextCacheBuilderValue;
    }

    MacroValue getNewCacheBuilder() {

        return this.NewCacheBuilderValue;
    }

    MacroValue getDirectivesCalls() {

        return this.DirectivesCallsValue;
    }

    MacroValue getInternalsCalls() {

        return this.InternalsCallsValue;
    }

    MacroValue getMacroBodyParts() {

        return this.MacroBodyPartsValue;
    }

    MacroValue getPublic() {

        return this.PublicValue;
    }

    MacroValue getOverride() {

        return this.OverrideValue;
    }

    private void initContextParamInternals(
            Context context) {

        for (Macro macro : this.list_ContextParam) {
            macro.apply(new InternalsInitializer("ContextParam") {

                @Override
                void setContextParam(
                        MContextParam mContextParam) {

                }
            });
        }
    }

    private void initContextCacheBuilderInternals(
            Context context) {

        for (Macro macro : this.list_ContextCacheBuilder) {
            macro.apply(new InternalsInitializer("ContextCacheBuilder") {

                @Override
                void setContextCacheBuilder(
                        MContextCacheBuilder mContextCacheBuilder) {

                }
            });
        }
    }

    private void initNewCacheBuilderInternals(
            Context context) {

        for (Macro macro : this.list_NewCacheBuilder) {
            macro.apply(new InternalsInitializer("NewCacheBuilder") {

                @Override
                void setNewCacheBuilder(
                        MNewCacheBuilder mNewCacheBuilder) {

                }
            });
        }
    }

    private void initDirectivesCallsInternals(
            Context context) {

        for (Macro macro : this.list_DirectivesCalls) {
            macro.apply(new InternalsInitializer("DirectivesCalls") {

                @Override
                void setInitDirectiveCall(
                        MInitDirectiveCall mInitDirectiveCall) {

                }
            });
        }
    }

    private void initInternalsCallsInternals(
            Context context) {

        for (Macro macro : this.list_InternalsCalls) {
            macro.apply(new InternalsInitializer("InternalsCalls") {

                @Override
                void setInitInternalsCall(
                        MInitInternalsCall mInitInternalsCall) {

                }
            });
        }
    }

    private void initMacroBodyPartsInternals(
            Context context) {

        for (Macro macro : this.list_MacroBodyParts) {
            macro.apply(new InternalsInitializer("MacroBodyParts") {

                @Override
                void setInitStringBuilder(
                        MInitStringBuilder mInitStringBuilder) {

                }

                @Override
                void setStringPart(
                        MStringPart mStringPart) {

                }

                @Override
                void setParamInsertPart(
                        MParamInsertPart mParamInsertPart) {

                }

                @Override
                void setEolPart(
                        MEolPart mEolPart) {

                }

                @Override
                void setInsertMacroPart(
                        MInsertMacroPart mInsertMacroPart) {

                }

                @Override
                void setAddIndent(
                        MAddIndent mAddIndent) {

                }

                @Override
                void setIndentPart(
                        MIndentPart mIndentPart) {

                }
            });
        }
    }

    private void initPublicInternals(
            Context context) {

        for (Macro macro : this.list_Public) {
            macro.apply(new InternalsInitializer("Public") {

                @Override
                void setPublic(
                        MPublic mPublic) {

                }
            });
        }
    }

    private void initOverrideInternals(
            Context context) {

        for (Macro macro : this.list_Override) {
            macro.apply(new InternalsInitializer("Override") {

                @Override
                void setOverride(
                        MOverride mOverride) {

                }
            });
        }
    }

    private void initContextParamDirectives() {

    }

    private void initContextCacheBuilderDirectives() {

        StringBuilder sb1 = new StringBuilder();
        sb1.append("this.cacheBuilder");
        this.ContextCacheBuilderNone = new DNone(sb1.toString());
        this.ContextCacheBuilderValue.setNone(this.ContextCacheBuilderNone);
    }

    private void initNewCacheBuilderDirectives() {

        StringBuilder sb1 = new StringBuilder();
        sb1.append("this.cacheBuilder = cache_builder");
        this.NewCacheBuilderNone = new DNone(sb1.toString());
        this.NewCacheBuilderValue.setNone(this.NewCacheBuilderNone);
        StringBuilder sb2 = new StringBuilder();
        sb2.append(LINE_SEPARATOR);
        this.NewCacheBuilderBeforeFirst = new DBeforeFirst(sb2.toString());
        this.NewCacheBuilderValue
                .setBeforeFirst(this.NewCacheBuilderBeforeFirst);
    }

    private void initDirectivesCallsDirectives() {

        StringBuilder sb1 = new StringBuilder();
        sb1.append(LINE_SEPARATOR);
        this.DirectivesCallsSeparator = new DSeparator(sb1.toString());
        this.DirectivesCallsValue.setSeparator(this.DirectivesCallsSeparator);
        StringBuilder sb2 = new StringBuilder();
        sb2.append(LINE_SEPARATOR);
        this.DirectivesCallsBeforeFirst = new DBeforeFirst(sb2.toString());
        this.DirectivesCallsValue
                .setBeforeFirst(this.DirectivesCallsBeforeFirst);
        StringBuilder sb3 = new StringBuilder();
        sb3.append(LINE_SEPARATOR);
        this.DirectivesCallsAfterLast = new DAfterLast(sb3.toString());
        this.DirectivesCallsValue.setAfterLast(this.DirectivesCallsAfterLast);
    }

    private void initInternalsCallsDirectives() {

        StringBuilder sb1 = new StringBuilder();
        sb1.append(LINE_SEPARATOR);
        this.InternalsCallsSeparator = new DSeparator(sb1.toString());
        this.InternalsCallsValue.setSeparator(this.InternalsCallsSeparator);
        StringBuilder sb2 = new StringBuilder();
        sb2.append(LINE_SEPARATOR);
        this.InternalsCallsBeforeFirst = new DBeforeFirst(sb2.toString());
        this.InternalsCallsValue.setBeforeFirst(this.InternalsCallsBeforeFirst);
        StringBuilder sb3 = new StringBuilder();
        sb3.append(LINE_SEPARATOR);
        this.InternalsCallsAfterLast = new DAfterLast(sb3.toString());
        this.InternalsCallsValue.setAfterLast(this.InternalsCallsAfterLast);
    }

    private void initMacroBodyPartsDirectives() {

        StringBuilder sb1 = new StringBuilder();
        sb1.append(LINE_SEPARATOR);
        this.MacroBodyPartsSeparator = new DSeparator(sb1.toString());
        this.MacroBodyPartsValue.setSeparator(this.MacroBodyPartsSeparator);
        StringBuilder sb2 = new StringBuilder();
        sb2.append(LINE_SEPARATOR);
        this.MacroBodyPartsBeforeFirst = new DBeforeFirst(sb2.toString());
        this.MacroBodyPartsValue.setBeforeFirst(this.MacroBodyPartsBeforeFirst);
        StringBuilder sb3 = new StringBuilder();
        sb3.append(LINE_SEPARATOR);
        this.MacroBodyPartsAfterLast = new DAfterLast(sb3.toString());
        this.MacroBodyPartsValue.setAfterLast(this.MacroBodyPartsAfterLast);
    }

    private void initPublicDirectives() {

        StringBuilder sb1 = new StringBuilder();
        sb1.append(" ");
        this.PublicAfterLast = new DAfterLast(sb1.toString());
        this.PublicValue.setAfterLast(this.PublicAfterLast);
    }

    private void initOverrideDirectives() {

    }

    @Override
    void apply(
            InternalsInitializer internalsInitializer) {

        internalsInitializer.setMacroBuilder(this);
    }

    public String build() {

        CacheBuilder cache_builder = this.cacheBuilder;

        if (cache_builder == null) {
            cache_builder = new CacheBuilder();
        }
        else if (cache_builder.getExpansion() == null) {
            throw new InternalException("Cycle detection detected lately");
        }
        else {
            return cache_builder.getExpansion();
        }
        this.cacheBuilder = cache_builder;
        List<String> indentations = new LinkedList<>();

        initContextParamInternals(null);
        initContextCacheBuilderInternals(null);
        initNewCacheBuilderInternals(null);
        initDirectivesCallsInternals(null);
        initInternalsCallsInternals(null);
        initMacroBodyPartsInternals(null);
        initPublicInternals(null);
        initOverrideInternals(null);

        initContextParamDirectives();
        initContextCacheBuilderDirectives();
        initNewCacheBuilderDirectives();
        initDirectivesCallsDirectives();
        initInternalsCallsDirectives();
        initMacroBodyPartsDirectives();
        initPublicDirectives();
        initOverrideDirectives();

        StringBuilder sb0 = new StringBuilder();

        sb0.append(buildOverride());
        sb0.append(LINE_SEPARATOR);
        sb0.append(buildPublic());
        sb0.append("String build(");
        sb0.append(buildContextParam());
        sb0.append(") ");
        sb0.append("{");
        sb0.append(LINE_SEPARATOR);
        sb0.append(LINE_SEPARATOR);
        sb0.append("    CacheBuilder cache_builder = ");
        sb0.append(buildContextCacheBuilder());
        sb0.append(";");
        sb0.append(LINE_SEPARATOR);
        sb0.append(LINE_SEPARATOR);
        sb0.append("    if(cache_builder == null) ");
        sb0.append("{");
        sb0.append(LINE_SEPARATOR);
        sb0.append("        cache_builder = new CacheBuilder();");
        sb0.append(LINE_SEPARATOR);
        sb0.append("    }");
        sb0.append(LINE_SEPARATOR);
        sb0.append("    else if(cache_builder.getExpansion() == null) ");
        sb0.append("{");
        sb0.append(LINE_SEPARATOR);
        sb0.append(
                "        throw new InternalException(\"Cycle detection detected lately\");");
        sb0.append(LINE_SEPARATOR);
        sb0.append("    }");
        sb0.append(LINE_SEPARATOR);
        sb0.append("    else ");
        sb0.append("{");
        sb0.append(LINE_SEPARATOR);
        sb0.append("        return cache_builder.getExpansion();");
        sb0.append(LINE_SEPARATOR);
        sb0.append("    }");
        sb0.append(LINE_SEPARATOR);
        sb0.append("    ");
        sb0.append(buildNewCacheBuilder());
        sb0.append(";");
        sb0.append(LINE_SEPARATOR);
        sb0.append("    List<String> indentations = new LinkedList<>();");
        sb0.append(LINE_SEPARATOR);
        sb0.append(LINE_SEPARATOR);
        StringBuilder sb1 = new StringBuilder();
        StringBuilder sb2 = new StringBuilder();
        sb2.append("    ");
        indentations.add(sb2.toString());
        sb1.append(buildInternalsCalls());
        sb1.append(buildDirectivesCalls());
        sb0.append(applyIndent(sb1.toString(),
                indentations.remove(indentations.size() - 1)));
        sb0.append(LINE_SEPARATOR);
        sb0.append(LINE_SEPARATOR);
        sb0.append("    StringBuilder sb0 = new StringBuilder();");
        sb0.append(LINE_SEPARATOR);
        StringBuilder sb3 = new StringBuilder();
        StringBuilder sb4 = new StringBuilder();
        sb4.append("    ");
        indentations.add(sb4.toString());
        sb3.append(buildMacroBodyParts());
        sb0.append(applyIndent(sb3.toString(),
                indentations.remove(indentations.size() - 1)));
        sb0.append(LINE_SEPARATOR);
        sb0.append("    cache_builder.setExpansion(sb0.toString());");
        sb0.append(LINE_SEPARATOR);
        sb0.append("    return sb0.toString();");
        sb0.append(LINE_SEPARATOR);
        sb0.append("}");
        cache_builder.setExpansion(sb0.toString());
        return sb0.toString();
    }

    @Override
    String build(
            Context context) {

        return build();
    }

    private void setMacros(
            Macros macros) {

        if (macros == null) {
            throw new InternalException("macros cannot be null");
        }

        this.macros = macros;
    }
}
