/*
 * Copyright (c) 2017-2025 XMLmind Software. All rights reserved.
 *
 * Author: Hussein Shafie
 *
 * This file is part of the XMLmind Assembly Processor project.
 * For conditions of distribution and use, see the accompanying LEGAL.txt file.
 */
package com.xmlmind.xinclude;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import static javax.xml.XMLConstants.XML_NS_URI;
import org.w3c.dom.Document;
import com.xmlmind.util.URLUtil;
import com.xmlmind.util.Console;
import com.xmlmind.domutil.DOMUtil;
import com.xmlmind.domutil.LoaderImpl;
import static com.xmlmind.xinclude.XIncluder.XINCLUDE_NS_URI;

/**
 * An implementation of {@link com.xmlmind.domutil.Loader} which makes use 
 * of the XInclude 1.1 processor contained in this package.
 */
public final class XLoader extends LoaderImpl {
    private String idAttrNamespace, idAttrLocalName;
    private String[] langAttrNames;

    // -----------------------------------------------------------------------

    public XLoader() {
        this(null);
    }

    public XLoader(Console c) {
        super(/*xincludeAware*/ false, c);

        useXMLId();
        useXMLLang();
    }

    /**
     * Use "<code>xml:id</code>" as the ID attribute.
     * <p>Needed to process XIncludes in loaded pages.
     * <p>This setting is the default one.
     */
    public void useXMLId() {
        idAttrNamespace = XML_NS_URI;
        idAttrLocalName = "id";
    }

    /**
     * Use "<code>id</code>" as the ID attribute.
     * <p>Needed to process XIncludes in loaded pages.
     */
    public void useId() {
        idAttrNamespace = null;
        idAttrLocalName = "id";
    }

    /**
     * Use "<code>xml:lang</code>" as the language attribute.
     * <p>Needed to process XIncludes in loaded pages.
     * <p>This setting is the default one.
     */
    public void useXMLLang() {
        langAttrNames = new String[] { XML_NS_URI, "lang" };
    }
    
    /**
     * Use "<code>lang</code>" as the language attribute.
     * <p>Needed to process XIncludes in loaded pages.
     */
    public void useLang() {
        langAttrNames = new String[] { null, "lang" };
    }

    /**
     * Use both "<code>xml:lang</code>" and "<code>lang</code>" as 
     * the language attributes.
     * <p>Needed to process XIncludes in loaded pages.
     */
    public void useBothLang() {
        langAttrNames = new String[] { XML_NS_URI, "lang", null, "lang" };
    }

    @Override
    public Document load(InputStream in, URL url) 
        throws IOException {
        Document doc = super.load(in, url);

        if (DOMUtil.findElementByName(doc, XINCLUDE_NS_URI,"include") != null) {
            XIncluder xincluder = new XIncluder(console);
            xincluder.setIdAttribute(idAttrNamespace, idAttrLocalName);
            xincluder.setLangAttributes(langAttrNames);

            if (!xincluder.process(doc)) {
                String location = "???";
                if (url != null) {
                    location = URLUtil.toLabel(url);
                }
                throw new IOException(Msg.msg("cannotProcessXIncludes", 
                                              location));
            }
        }

        return doc;
    }
}
