/* $Id: QedeqBoFactory.java,v 1.23 2005/12/17 10:31:31 m31 Exp $
 *
 * This file is part of the project "Hilbert II" - http://www.qedeq.org
 *
 * Copyright 2000-2005,  Michael Meyling <mime@qedeq.org>.
 *
 * "Hilbert II" is free software; you can redistribute
 * it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 */

package org.qedeq.kernel.bo.control;

import org.qedeq.kernel.base.elli.Element;
import org.qedeq.kernel.base.module.Author;
import org.qedeq.kernel.base.module.AuthorList;
import org.qedeq.kernel.base.module.Axiom;
import org.qedeq.kernel.base.module.Chapter;
import org.qedeq.kernel.base.module.ChapterList;
import org.qedeq.kernel.base.module.Definition;
import org.qedeq.kernel.base.module.FormulaOrTerm;
import org.qedeq.kernel.base.module.Header;
import org.qedeq.kernel.base.module.Import;
import org.qedeq.kernel.base.module.ImportList;
import org.qedeq.kernel.base.module.Latex;
import org.qedeq.kernel.base.module.LatexList;
import org.qedeq.kernel.base.module.LinkList;
import org.qedeq.kernel.base.module.Location;
import org.qedeq.kernel.base.module.LocationList;
import org.qedeq.kernel.base.module.Node;
import org.qedeq.kernel.base.module.Proof;
import org.qedeq.kernel.base.module.ProofList;
import org.qedeq.kernel.base.module.Proposition;
import org.qedeq.kernel.base.module.Qedeq;
import org.qedeq.kernel.base.module.Rule;
import org.qedeq.kernel.base.module.Section;
import org.qedeq.kernel.base.module.SectionList;
import org.qedeq.kernel.base.module.Specification;
import org.qedeq.kernel.base.module.Subsection;
import org.qedeq.kernel.base.module.SubsectionList;
import org.qedeq.kernel.base.module.UsedByList;
import org.qedeq.kernel.base.module.VariableList;
import org.qedeq.kernel.bo.module.AuthorBo;
import org.qedeq.kernel.bo.module.AuthorListBo;
import org.qedeq.kernel.bo.module.AxiomBo;
import org.qedeq.kernel.bo.module.ChapterBo;
import org.qedeq.kernel.bo.module.ChapterListBo;
import org.qedeq.kernel.bo.module.DefinitionBo;
import org.qedeq.kernel.bo.module.DuplicateLanguageEntryException;
import org.qedeq.kernel.bo.module.FormulaOrTermBo;
import org.qedeq.kernel.bo.module.HeaderBo;
import org.qedeq.kernel.bo.module.ImportBo;
import org.qedeq.kernel.bo.module.ImportListBo;
import org.qedeq.kernel.bo.module.LatexBo;
import org.qedeq.kernel.bo.module.LatexListBo;
import org.qedeq.kernel.bo.module.LinkListBo;
import org.qedeq.kernel.bo.module.LocationBo;
import org.qedeq.kernel.bo.module.LocationListBo;
import org.qedeq.kernel.bo.module.NodeBo;
import org.qedeq.kernel.bo.module.NullPointerListEntryException;
import org.qedeq.kernel.bo.module.ProofBo;
import org.qedeq.kernel.bo.module.ProofListBo;
import org.qedeq.kernel.bo.module.PropositionBo;
import org.qedeq.kernel.bo.module.QedeqBo;
import org.qedeq.kernel.bo.module.RuleBo;
import org.qedeq.kernel.bo.module.SectionBo;
import org.qedeq.kernel.bo.module.SectionListBo;
import org.qedeq.kernel.bo.module.SpecificationBo;
import org.qedeq.kernel.bo.module.SubsectionBo;
import org.qedeq.kernel.bo.module.SubsectionListBo;
import org.qedeq.kernel.bo.module.UsedByListBo;
import org.qedeq.kernel.bo.module.VariableListBo;


/**
 * A factory for creating {@link org.qedeq.kernel.bo.module.QedeqBo}s.
 *
 * LATER mime 20050707: use director pattern or transfer creation methods
 *  into BOs or use visitor pattern
 * @version $Revision: 1.23 $
 * @author    Michael Meyling
 */
public class QedeqBoFactory {

    /** Qedeq module business object. */
    private QedeqBo qedeq;

    /** Qedeq module input object. */
    private Qedeq original;

    /** Current context during creation. */
    private Context currentContext;

    /**
     * Constructor.
     *
     * @param   globalContext     Module location information.
     */
    protected QedeqBoFactory(final String globalContext) {
        currentContext = new Context(globalContext);
    }

    /**
     * Create {@link QedeqBo} out of an {@link Qedeq} instance.
     * During that procedure some basic checking is done. E.g. the uniqueness of entries
     * is tested. The resulting business object has no references to the original
     * {@link Qedeq} instance.
     * <p>
     * During the creation process the caller must assert that no modifications are made
     * to the {@link Qedeq} instance including its referenced objects.
     *
     * @param   globalContext     Module location information.
     * @param   original    Basic qedeq module object.
     * @return  Filled qedeq business object. Is equal to the parameter <code>qedeq</code>.
     * @throws  IllegalModuleDataException  Basic semantic error occurred.
     */
    public static QedeqBo createQedeq(final String globalContext, final Qedeq original)
            throws IllegalModuleDataException {
        final QedeqBoFactory creator = new QedeqBoFactory(globalContext);
        return creator.create(original);
    }

    /**
     * Create {@link QedeqBo} out of an {@link Qedeq} instance.
     * During that procedure some basic checking is done. E.g. the uniqueness of entries
     * is tested. The resulting business object has no references to the original
     * {@link Qedeq} instance.
     * <p>
     * During the creation process the caller must assert that no modifications are made
     * to the {@link Qedeq} instance including its referenced objects.
     *
     * @param   original    Basic qedeq module object.
     * @return  Filled header business object. Is equal to the parameter <code>header</code>.
     * @throws  IllegalModuleDataException  Basic semantic error occurred.
     */
    protected final QedeqBo create(final Qedeq original) throws IllegalModuleDataException {
        this.original = original;
        getCurrentContext().setLocationWithinModule("");
        if (original == null) {
            qedeq = null;
            return qedeq;
        }
        qedeq = new QedeqBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (original.getHeader() != null) {
            getCurrentContext().setLocationWithinModule(context + "getHeader()");
            qedeq.setHeader(create(original.getHeader()));
        }
        if (original.getChapterList() != null) {
            getCurrentContext().setLocationWithinModule(context + "getChapterList()");
            qedeq.setChapterList(create(original.getChapterList()));
        }
        return qedeq;
    }

    /**
     * Create {@link HeaderBo} out of an {@link Header} instance.
     * During that procedure some basic checking is done. E.g. the uniqueness of entries
     * is tested. The resulting business object has no references to the original
     * {@link Header} instance.
     * <p>
     * During the creation process the caller must assert that no modifications are made
     * to the {@link Header} instance including its referenced objects.
     *
     * @param   header  Basic header object.
     * @return  Filled header business object. Is equal to the parameter <code>header</code>.
     * @throws  IllegalModuleDataException  Basic semantic error occurred.
     */
    private final HeaderBo create(final Header header)
            throws IllegalModuleDataException {
        if (header == null) {
            return null;
        }
        final HeaderBo h = new HeaderBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (header.getTitle() != null) {
            setLocationWithinModule(context + ".getTitle()");
            h.setTitle(create(header.getTitle()));
        }
        if (header.getAuthorList() != null) {
            setLocationWithinModule(context + ".getAuthorList()");
            h.setAuthorList(create(header.getAuthorList()));
        }
        if (header.getSummary() != null) {
            setLocationWithinModule(context + ".getSummary()");
            h.setSummary(create(header.getSummary()));
        }
        if (header.getEmail() != null) {
            setLocationWithinModule(context + ".getEmail()");
            h.setEmail(header.getEmail());
        }
        if (header.getSpecification() != null) {
            setLocationWithinModule(context + ".getSpecification()");
            h.setSpecification(create(header.getSpecification()));
        }
        if (header.getImportList() != null) {
            setLocationWithinModule(context + ".getImportList()");
            h.setImportList(create(header.getImportList()));
        }
        if (header.getUsedByList() != null) {
            setLocationWithinModule(context + ".getUsedByList()");
            h.setUsedByList(create(header.getUsedByList()));
        }
        return h;
    }

    /**
     * Create {@link UsedByListBo} out of an {@link UsedByList} instance.
     * During that procedure some basic checking is done. E.g. the uniqueness of entries
     * is tested. The resulting business object has no references to the original
     * {@link UsedByList} instance.
     * <p>
     * During the creation process the caller must assert that no modifications are made
     * to the {@link UsedByList} instance including its referenced objects.
     *
     * @param   usedByList  Basic header object.
     * @return  Filled used by business object. Is equal to the parameter <code>usedByList</code>.
     */
    private final UsedByListBo create(final UsedByList usedByList) {
        if (usedByList == null) {
            return null;
        }
        final String context = getCurrentContext().getLocationWithinModule();
        final UsedByListBo list = new UsedByListBo();
        for (int i = 0; i < usedByList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            list.add(create(usedByList.get(i)));
        }
        return list;
    }

    private final ImportListBo create(final ImportList importList) {
        if (importList == null) {
            return null;
        }
        final String context = getCurrentContext().getLocationWithinModule();
        final ImportListBo list = new ImportListBo();
        for (int i = 0; i < importList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            list.add(create(importList.get(i)));
        }
        return list;
    }

    private final ImportBo create(final Import imp) {
        if (imp == null) {
            return null;
        }
        final ImportBo i = new ImportBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (imp.getLabel() != null) {
            setLocationWithinModule(context + ".getLabel()");
            i.setLabel(imp.getLabel());
        }
        if (imp.getSpecification() != null) {
            setLocationWithinModule(context + ".getSpecification()");
            i.setSpecification(create(imp.getSpecification()));
        }
        return i;
    }

    private final SpecificationBo create(final Specification specification) {
        if (specification == null) {
            return null;
        }
        final SpecificationBo s = new SpecificationBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (specification.getName() != null) {
            setLocationWithinModule(context + ".getName()");
            s.setName(specification.getName());
        }
        if (specification.getRuleVersion() != null) {
            setLocationWithinModule(context + ".getRuleVersion()");
            s.setRuleVersion(specification.getRuleVersion());
        }
        if (specification.getLocationList() != null) {
            setLocationWithinModule(context + ".getLocationList()");
            s.setLocationList(create(specification.getLocationList()));
        }
        return s;
    }

    private final LocationListBo create(final LocationList locationList) {
        if (locationList == null) {
            return null;
        }
        final LocationListBo list = new LocationListBo();
        final String context = getCurrentContext().getLocationWithinModule();
        for (int i = 0; i < locationList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            list.add(create(locationList.get(i)));
        }
        return list;
    }

    private final LocationBo create(final Location location) {
        if (location == null) {
            return null;
        }
        final LocationBo loc = new LocationBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (location.getLocation() != null) {
            setLocationWithinModule(context + ".getLocation()");
            loc.setLocation(location.getLocation());
        }
        return loc;
    }

    private final AuthorListBo create(final AuthorList authorList) {
        if (authorList == null) {
            return null;
        }
        final AuthorListBo list = new AuthorListBo();
        final String context = getCurrentContext().getLocationWithinModule();
        for (int i = 0; i < authorList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            list.add(create(authorList.get(i)));
        }
        return list;
    }

    private final AuthorBo create(final Author author) {
        if (author == null) {
            return null;
        }
        final AuthorBo a = new AuthorBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (author.getName() != null) {
            setLocationWithinModule(context + ".getName()");
            a.setName(create(author.getName()));
        }
        if (author.getEmail() != null) {
            setLocationWithinModule(context + ".getEmail()");
            a.setEmail(author.getEmail());
        }
        return a;
    }

    private final ChapterListBo create(final ChapterList chapterList)
            throws IllegalModuleDataException {
        if (chapterList == null) {
            return null;
        }
        final ChapterListBo list = new ChapterListBo();
        final String context = getCurrentContext().getLocationWithinModule();
        for (int i = 0; i < chapterList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            list.add(create(chapterList.get(i)));
        }
        return list;
    }

    private final ChapterBo create(final Chapter chapter)
            throws IllegalModuleDataException {
        if (chapter == null) {
            return null;
        }
        final ChapterBo c = new ChapterBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (chapter.getTitle() != null) {
            setLocationWithinModule(context + ".getTitle()");
            c.setTitle(create(chapter.getTitle()));
        }
        if (chapter.getNoNumber() != null) {
            setLocationWithinModule(context + ".getNoNumber()");
            c.setNoNumber(chapter.getNoNumber());
        }
        if (chapter.getIntroduction() != null) {
            setLocationWithinModule(context + ".getIntroduction()");
            c.setIntroduction(create(chapter.getIntroduction()));
        }
        if (chapter.getSectionList() != null) {
            setLocationWithinModule(context + ".getSectionList()");
            c.setSectionList(create(chapter.getSectionList()));
        }
        return c;
    }

    private final SectionListBo create(final SectionList sectionList)
            throws IllegalModuleDataException {
        if (sectionList == null) {
            return null;
        }
        final SectionListBo list = new SectionListBo();
        final String context = getCurrentContext().getLocationWithinModule();
        for (int i = 0; i < sectionList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            list.add(create(sectionList.get(i)));
        }
        return list;
    }

    private final SectionBo create(final Section section)
            throws IllegalModuleDataException {
        if (section == null) {
            return null;
        }
        final SectionBo s = new SectionBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (section.getTitle() != null) {
            setLocationWithinModule(context + ".getTitle()");
            s.setTitle(create(section.getTitle()));
        }
        if (section.getNoNumber() != null) {
            setLocationWithinModule(context + ".getNoNumber()");
            s.setNoNumber(section.getNoNumber());
        }
        if (section.getIntroduction() != null) {
            setLocationWithinModule(context + ".getIntroduction()");
            s.setIntroduction(create(section.getIntroduction()));
        }
        if (section.getSubsectionList() != null) {
            setLocationWithinModule(context + ".getSubsectionList()");
            s.setSubsectionList(create(section.getSubsectionList()));
        }
        return s;
    }

    private final SubsectionListBo create(final SubsectionList subsectionList)
            throws IllegalModuleDataException {
        if (subsectionList == null) {
            return null;
        }
        final SubsectionListBo list = new SubsectionListBo();
        final String context = getCurrentContext().getLocationWithinModule();
        for (int i = 0; i < subsectionList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            // TODO mime 20050608: here the Subsection context is type dependently specified
            if (subsectionList.get(i) instanceof Subsection) {
                list.add(create((Subsection) subsectionList.get(i)));
            } else if (subsectionList.get(i) instanceof Node) {
                list.add(create((Node) subsectionList.get(i)));
            } else {
                throw new IllegalArgumentException("unexpected subsection type: "
                    + subsectionList.get(i).getClass());
            }
        }
        return list;
    }

    private final SubsectionBo create(final Subsection subsection)
            throws IllegalModuleDataException {
        if (subsection == null) {
            return null;
        }
        final SubsectionBo s = new SubsectionBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (subsection.getTitle() != null) {
            setLocationWithinModule(context + ".getTitle()");
            s.setTitle(create(subsection.getTitle()));
        }
        if (subsection.getLevel() != null) {
            setLocationWithinModule(context + ".getLevel()");
            s.setLevel(subsection.getLevel());
        }
        if (subsection.getLatex() != null) {
            setLocationWithinModule(context + ".getLatex()");
            s.setLatex(create(subsection.getLatex()));
        }
        return s;
    }

    private final NodeBo create(final Node node)
            throws IllegalModuleDataException {
        if (node == null) {
            return null;
        }
        final NodeBo n = new NodeBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (node.getName() != null) {
            setLocationWithinModule(context + ".getName()");
            n.setName(create(node.getName()));
        }
        if (node.getId() != null) {
            setLocationWithinModule(context + ".getId()");
            n.setId(node.getId());
        }
        if (node.getLevel() != null) {
            setLocationWithinModule(context + ".getLevel()");
            n.setLevel(node.getLevel());
        }
        if (node.getTitle() != null) {
            setLocationWithinModule(context + ".getTitle()");
            n.setTitle(create(node.getTitle()));
        }
        if (node.getPrecedingText() != null) {
            setLocationWithinModule(context + ".getPrecedingText()");
            n.setPrecedingText(create(node.getPrecedingText()));
        }
        if (node.getNodeType() != null) {
            setLocationWithinModule(context + ".getNodeType()");
            if (node.getNodeType() instanceof Axiom) {
                setLocationWithinModule(context + ".getNodeType().getAxiom()");
                n.setNodeType(create((Axiom) node.getNodeType()));
            } else if (node.getNodeType() instanceof Definition) {
                setLocationWithinModule(context + ".getNodeType().getDefinition()");
                n.setNodeType(create((Definition) node.getNodeType()));
            } else if (node.getNodeType() instanceof Proposition) {
                setLocationWithinModule(context + ".getNodeType().getProposition()");
                n.setNodeType(create((Proposition) node.getNodeType()));
            } else if (node.getNodeType() instanceof Rule) {
                setLocationWithinModule(context + ".getNodeType().getRule()");
                n.setNodeType(create((Rule) node.getNodeType()));
            } else {
                throw new IllegalArgumentException("unexpected node type: "
                    + node.getNodeType().getClass());
            }
        }
        if (node.getSucceedingText() != null) {
            setLocationWithinModule(context + ".getSucceedingText()");
            n.setSucceedingText(create(node.getSucceedingText()));
        }
        setLocationWithinModule(context);
        getQedeqCreated().getModuleLabels().addNode(getCurrentContext(), n);
        return n;
    }

    private final AxiomBo create(final Axiom axiom) throws IllegalModuleDataException {
        if (axiom == null) {
            return null;
        }
        final AxiomBo a = new AxiomBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (axiom.getFormula() != null) {
            setLocationWithinModule(context + ".getFormula()");
            a.setFormula(create(axiom.getFormula()));
        }
        if (axiom.getDescription() != null) {
            setLocationWithinModule(context + ".getDescription()");
            a.setDescription(create(axiom.getDescription()));
        }
        return a;
    }

    private final DefinitionBo create(final Definition definition)
            throws IllegalModuleDataException {
        if (definition == null) {
            return null;
        }
        final DefinitionBo d = new DefinitionBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (definition.getType() != null) {
            setLocationWithinModule(context + ".getType()");
            d.setType(definition.getType());
        }
        if (definition.getLatexPattern() != null) {
            setLocationWithinModule(context + ".getLatexPattern()");
            d.setLatexPattern(definition.getLatexPattern());
        }
        if (definition.getArgumentNumber() != null) {
            setLocationWithinModule(context + ".getArgumentNumber()");
            d.setArgumentNumber(definition.getArgumentNumber());
        }
        if (definition.getVariableList() != null) {
            setLocationWithinModule(context + ".getVariableList()");
            d.setVariableList(create(definition.getVariableList()));
        }
        if (definition.getFormulaOrTerm() != null) {
            setLocationWithinModule(context + ".getFormulaOrTerm()");
            d.setFormulaOrTerm(create(definition.getFormulaOrTerm()));
        }
        if (definition.getDescription() != null) {
            setLocationWithinModule(context + ".getDescription()");
            d.setDescription(create(definition.getDescription()));
        }
        return d;
    }

    private final PropositionBo create(final Proposition proposition)
            throws IllegalModuleDataException {
        if (proposition == null) {
            return null;
        }
        final PropositionBo p = new PropositionBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (proposition.getFormula() != null) {
            setLocationWithinModule(context + ".getFormula()");
            p.setFormula(create(proposition.getFormula()));
        }
        if (proposition.getDescription() != null) {
            setLocationWithinModule(context + ".getDescription()");
            p.setDescription(create(proposition.getDescription()));
        }
        if (proposition.getProofList() != null) {
            setLocationWithinModule(context + ".getProofList()");
            p.setProofList(create(proposition.getProofList()));
        }
        return p;
    }

    private final RuleBo create(final Rule rule)
            throws IllegalModuleDataException {
        if (rule == null) {
            return null;
        }
        final RuleBo r = new RuleBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (rule.getName() != null) {
            setLocationWithinModule(context + ".getName()");
            r.setName(rule.getName());
        }
        if (rule.getLinkList() != null) {
            setLocationWithinModule(context + ".getLinkList()");
            r.setLinkList(create(rule.getLinkList()));
        }
        if (rule.getDescription() != null) {
            setLocationWithinModule(context + ".getDescription()");
            r.setDescription(create(rule.getDescription()));
        }
        if (rule.getProofList() != null) {
            setLocationWithinModule(context + ".getProofList()");
            r.setProofList(create(rule.getProofList()));
        }
        return r;
    }

    private final LinkListBo create(final LinkList linkList) {
        if (linkList == null) {
            return null;
        }
        final LinkListBo list = new LinkListBo();
        final String context = getCurrentContext().getLocationWithinModule();
        for (int i = 0; i < linkList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            list.add(linkList.get(i));
        }
        return list;
    }

    private final VariableListBo create(final VariableList variableList) {
        if (variableList == null) {
            return null;
        }
        final VariableListBo list = new VariableListBo();
        final String context = getCurrentContext().getLocationWithinModule();
        for (int i = 0; i < variableList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            list.add(create(variableList.get(i)));
        }
        return list;
    }

    private final ProofListBo create(final ProofList proofList)
            throws IllegalModuleDataException {
        if (proofList == null) {
            return null;
        }
        final ProofListBo list = new ProofListBo();
        final String context = getCurrentContext().getLocationWithinModule();
        for (int i = 0; i < proofList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            list.add(create(proofList.get(i)));
        }
        return list;
    }

    private final ProofBo create(final Proof proof)
            throws IllegalModuleDataException {
        if (proof == null) {
            return null;
        }
        final ProofBo p = new ProofBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (proof.getNonFormalProof() != null) {
            setLocationWithinModule(context + ".getNonFormalProof()");
            p.setNonFormalProof(create(proof.getNonFormalProof()));
        }
        return p;
    }

    private final FormulaOrTermBo create(final FormulaOrTerm formulaOrTerm) {
        if (formulaOrTerm == null) {
            return null;
        }
        final FormulaOrTermBo f = new FormulaOrTermBo();
        final String context = getCurrentContext().getLocationWithinModule();
        if (formulaOrTerm.getElement() != null) {
            setLocationWithinModule(context + ".getElement()");
            f.setElement(create(formulaOrTerm.getElement()));
        }
        return f;
    }

    private final Element create(final Element element) {
        if (element == null) {
            return null;
        }
        final String context = getCurrentContext().getLocationWithinModule();
        // TODO mime 20050325: create element BO here? Answer: no BO but copy of
        // element should be made
        return element; 
    }


    private final LatexListBo create(final LatexList latexList)
            throws IllegalModuleDataException {
        if (latexList == null) {
            return null;
        }
        final LatexListBo list = new LatexListBo();
        final String context = getCurrentContext().getLocationWithinModule();
        for (int i = 0; i < latexList.size(); i++) {
            setLocationWithinModule(context + ".get(" + i + ")");
            try {
                list.add(create(latexList.get(i)));
            } catch (NullPointerListEntryException e) {
                throw new IllegalModuleDataException(e.getErrorCode(),
                    e.getMessage(), new Context(getCurrentContext()), e);
            } catch (DuplicateLanguageEntryException e) {
                throw new IllegalModuleDataException(e.getErrorCode(), e.getMessage(),
                    new Context(getCurrentContext()), new Context(getCurrentContext(), context
                        + ".get(" + (e.getIndex() + 1) + ")"), e);
            }
        }
        return list;
    }

    /**
     * Creates LaTeX business object.
     *
     * @param   latex   LaTeX object.
     * @return  LaTeX business object.
     */
    private final LatexBo create(final Latex latex) {
        if (latex == null) {
            return null;
        }
        final LatexBo lat = new LatexBo();
        // TODO mime 20050707: use here creation process also?
        lat.setLanguage(latex.getLanguage());
        lat.setLatex(latex.getLatex());
        return lat;
    }

    /**
     * Set location information where are we within the orginal module.
     *
     * @param   locationWithinModule    Location within module.
     */
    protected void setLocationWithinModule(final String locationWithinModule) {
        getCurrentContext().setLocationWithinModule(locationWithinModule);
    }

    /**
     * Get current context within original.
     *
     * @return  Current context.
     */
    protected final Context getCurrentContext() {
        return currentContext;
    }

    /**
     * Get original qedeq module.
     *
     * @return  Original qedeq module.
     */
    protected final Qedeq getQedeqOriginal() {
        return original;
    }

    /**
     * Get currently created qedeq module.
     *
     * @return  Currently created qedeq module.
     */
    protected final QedeqBo getQedeqCreated() {
        return qedeq;
    }

}
