All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.undercouch.citeproc.csl.internal.rendering.SNames Maven / Gradle / Ivy

package de.undercouch.citeproc.csl.internal.rendering;

import de.undercouch.citeproc.csl.internal.RenderContext;
import de.undercouch.citeproc.csl.internal.SElement;
import de.undercouch.citeproc.csl.internal.behavior.Affixes;
import de.undercouch.citeproc.csl.internal.behavior.FormattingAttributes;
import de.undercouch.citeproc.helper.NodeHelper;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.List;

/**
 * A names element from a style file
 * @author Michel Kraemer
 */
public class SNames implements SRenderingElement {
    private final String variableAttribute;
    private final Affixes affixes;
    private final int formattingAttributes;
    private final SSubstitute substitute;
    private final List elements = new ArrayList<>();

    /**
     * Creates the names element from an XML node
     * @param node the XML node
     */
    public SNames(Node node) {
        this(node, NodeHelper.getAttrValue(node, "variable"), true);
    }

    /**
     * Creates the names element from an XML node but with a different variable
     * @param node the XML node
     * @param variableAttribute the value of the variable attribute
     * @param parseSubstitute {@code true} if the substitute child element
     * should be parsed, {@code false} if it should be ignored
     */
    public SNames(Node node, String variableAttribute, boolean parseSubstitute) {
        String[] variables;
        if (variableAttribute == null) {
            variables = new String[0];
        } else {
            variables = variableAttribute.split("\\s+");
        }

        String delimiter = NodeHelper.getAttrValue(node, "delimiter");
        this.formattingAttributes = FormattingAttributes.of(node);

        boolean allFormCount = true;
        Node firstNameNode = null;
        for (String variable : variables) {
            List elementsForVariable = new ArrayList<>();
            SName name = null;
            Node nameNode = null;
            SLabel label = null;
            int namePos = -1;
            NodeList children = node.getChildNodes();
            for (int i = 0; i < children.getLength(); ++i) {
                Node c = children.item(i);
                String nodeName = c.getNodeName();
                if ("name".equals(nodeName)) {
                    name = new SName(c, variable);
                    nameNode = c;
                    if (namePos >= 0) {
                        elementsForVariable.set(namePos, name);
                    } else {
                        namePos = elementsForVariable.size();
                        elementsForVariable.add(name);
                    }
                } else if (label == null && "label".equals(nodeName)) {
                    label = new SLabel(c, variable);
                    elementsForVariable.add(label);
                }
            }

            if (name == null) {
                name = new SName(null, variable);
                elementsForVariable.add(0, name);
            }
            if (firstNameNode == null) {
                firstNameNode = nameNode;
            }

            allFormCount = allFormCount && name.getForm() == SName.FORM_COUNT;

            if (!elements.isEmpty() && delimiter != null) {
                elements.add((SRenderingElement)ctx -> {
                    RenderContext tmp = new RenderContext(ctx);
                    for (SElement e : elementsForVariable) {
                        e.render(tmp);
                    }
                    if (!tmp.getResult().isEmpty()) {
                        ctx.emit(delimiter);
                        ctx.emit(tmp.getResult());
                    }
                });
            } else {
                elements.addAll(elementsForVariable);
            }
        }

        this.variableAttribute = variableAttribute;

        if (parseSubstitute) {
            Node substituteNode = NodeHelper.findDirectChild(node, "substitute");
            if (substituteNode != null) {
                substitute = new SSubstitute(substituteNode, node);
            } else {
                substitute = null;
            }
        } else {
            substitute = null;
        }

        if (allFormCount) {
            elements.clear();
            elements.add(new SName(firstNameNode, variableAttribute));
            affixes = new Affixes();
        } else {
            affixes = new Affixes(node);
        }
    }

    /**
     * Get the value of the {@code variable} attribute
     * @return the attribute value
     */
    public String getVariableAttribute() {
        return variableAttribute;
    }

    @Override
    public void render(RenderContext ctx) {
        RenderContext tmp = new RenderContext(ctx);
        affixes.wrap(this::renderInternal).accept(tmp);

        if (tmp.getResult().isEmpty()) {
            if (substitute != null) {
                substitute.render(tmp);
            }
        }

        ctx.emit(tmp.getResult());
    }

    private void renderInternal(RenderContext ctx) {
        RenderContext child = new RenderContext(ctx);
        for (SElement e : elements) {
            e.render(child);
        }
        ctx.emit(child.getResult(), formattingAttributes);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy