class DocType extends AbstractTemplateEvent implements IDocType, IEngineTemplateEvent {

    // DOCTYPE nodes do not exist in text parsing, so we are safe expliciting markup structures here
    public static final String DEFAULT_KEYWORD = "DOCTYPE";
    public static final String DEFAULT_ELEMENT_NAME = "html";
    public static final String DEFAULT_TYPE_PUBLIC = "PUBLIC";
    public static final String DEFAULT_TYPE_SYSTEM = "SYSTEM";

    private final String keyword;
    private final String elementName;
    private final String type;
    private final String publicId;
    private final String systemId;
    private final String internalSubset;

    private final String docType;


    DocType() {
        this(null, null);
    }


    DocType(final String publicId, final String systemId) {
        this(DEFAULT_KEYWORD, DEFAULT_ELEMENT_NAME, publicId, systemId, null);
    }


    DocType(
            final String keyword,
            final String elementName,
            final String publicId,
            final String systemId,
            final String internalSubset) {
        super();
        this.keyword = keyword;
        this.elementName = elementName;
        this.type = computeType(publicId, systemId);
        this.publicId = publicId;
        this.systemId = systemId;
        this.internalSubset = internalSubset;
        this.docType = computeDocType();
    }


    DocType(
            final String docType,
            final String keyword,
            final String elementName,
            final String publicId,
            final String systemId,
            final String internalSubset,
            final String templateName, final int line, final int col) {
        super(templateName, line, col);
        this.keyword = keyword;
        this.elementName = elementName;
        this.type = computeType(publicId, systemId);
        this.publicId = publicId;
        this.systemId = systemId;
        this.internalSubset = internalSubset;
        this.docType = (docType != null? docType : computeDocType());
    }



    public String getKeyword() {
        return this.keyword;
    }

    public String getElementName() {
        return this.elementName;
    }

    public String getType() {
        return this.type;
    }

    public String getPublicId() {
        return this.publicId;
    }

    public String getSystemId() {
        return this.systemId;
    }

    public String getInternalSubset() {
        return this.internalSubset;
    }

    public String getDocType() {
        return this.docType;
    }




    private String computeDocType() {<FILL_FUNCTION_BODY>}




    private static String computeType(final String publicId, final String systemId) {

        if (publicId != null && systemId == null) {
            throw new IllegalArgumentException(
                    "DOCTYPE clause cannot have a non-null PUBLIC ID and a null SYSTEM ID");
        }

        if (publicId == null && systemId == null) {
            return null;
        }

        if (publicId != null) {
            return DEFAULT_TYPE_PUBLIC;
        }

        return DEFAULT_TYPE_SYSTEM;

    }




    public void accept(final IModelVisitor visitor) {
        visitor.visit(this);
    }


    public void write(final Writer writer) throws IOException {
        writer.write(this.docType);
    }




    // Meant to be called only from within the engine
    static DocType asEngineDocType(final IDocType docType) {

        if (docType instanceof DocType) {
            return (DocType) docType;
        }

        return new DocType(
                null,
                docType.getKeyword(),
                docType.getElementName(),
                docType.getPublicId(),
                docType.getSystemId(),
                docType.getInternalSubset(),
                docType.getTemplateName(), docType.getLine(), docType.getCol());

    }




    @Override
    public void beHandled(final ITemplateHandler handler) {
        handler.handleDocType(this);
    }




    @Override
    public String toString() {
        return getDocType();
    }


}


        final StringBuilder strBuilder = new StringBuilder(120);

        strBuilder.append("<!");
        strBuilder.append(this.keyword);
        strBuilder.append(' ');
        strBuilder.append(this.elementName);
        if (this.type != null) {
            strBuilder.append(' ');
            strBuilder.append(type);
            if (this.publicId != null) {
                strBuilder.append(" \"");
                strBuilder.append(this.publicId);
                strBuilder.append('"');
            }
            strBuilder.append(" \"");
            strBuilder.append(this.systemId);
            strBuilder.append('"');
        }
        if (this.internalSubset != null) {
            strBuilder.append(" [");
            strBuilder.append(this.internalSubset);
            strBuilder.append(']');
        }
        strBuilder.append('>');

        return strBuilder.toString();

    
<methods>public final int getCol() ,public final int getLine() ,public final java.lang.String getTemplateName() ,public final boolean hasLocation() <variables>final non-sealed int col,final non-sealed int line,final non-sealed java.lang.String templateName