/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.taglibs.standard.tlv;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;

import jakarta.servlet.jsp.tagext.PageData;
import jakarta.servlet.jsp.tagext.TagData;
import jakarta.servlet.jsp.tagext.TagLibraryValidator;
import jakarta.servlet.jsp.tagext.ValidationMessage;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.taglibs.standard.resources.Resources;
import org.apache.taglibs.standard.util.XmlUtil;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

/**
 * <p>A base class to support SAX-based validation in JSTL.</p>
 *
 * @author Shawn Bayern
 */
public abstract class JstlBaseTLV extends TagLibraryValidator {

    //*********************************************************************
    // Implementation Overview

    /*
     * We essentially just run the page through a SAX parser, handling
     * the callbacks that interest us.  The SAX parser is supplied by
     * subclasses using the protected getHandler() method.
     */

    protected abstract DefaultHandler getHandler();


    //*********************************************************************
    // Constants

    // parameter names
    private static final String EXP_ATT_PARAM = "expressionAttributes";

    // attributes
    protected static final String VAR = "var";
    protected static final String SCOPE = "scope";

    //scopes
    protected static final String PAGE_SCOPE = "page";
    protected static final String REQUEST_SCOPE = "request";
    protected static final String SESSION_SCOPE = "session";
    protected static final String APPLICATION_SCOPE = "application";

    // Relevant URIs
    protected final String JSP = "http://java.sun.com/JSP/Page";

    // types of sub-classes - used on method validate()
    private static final int TYPE_UNDEFINED = 0;
    protected static final int TYPE_CORE = 1;
    protected static final int TYPE_FMT = 2;
    protected static final int TYPE_SQL = 3;
    protected static final int TYPE_XML = 4;

    // which tlv is being validated
    private int tlvType = TYPE_UNDEFINED;

    //*********************************************************************
    // Validation and configuration state (protected)

    protected String uri;            // our taglib's uri (as passed by JSP container on XML View)
    protected String prefix;            // our taglib's prefix
    protected Vector messageVector;        // temporary error messages
    protected Map config;            // configuration (Map of Sets)
    protected boolean failed;            // have we failed >0 times?
    protected String lastElementId;        // the last element we've seen

    //*********************************************************************
    // Constructor and lifecycle management

    public JstlBaseTLV() {
        super();
        init();
    }

    private void init() {
        messageVector = null;
        prefix = null;
        config = null;
    }

    @Override
    public void release() {
        super.release();
        init();
    }


    //*********************************************************************
    // Validation entry point - this method is called by the sub-classes to 
    // do the validation.

    public synchronized ValidationMessage[] validate(
            int type, String prefix, String uri, PageData page) {
        try {
            this.tlvType = type;
            this.uri = uri;
            // initialize
            messageVector = new Vector();

            // save the prefix
            this.prefix = prefix;

            // parse parameters if necessary
            try {
                if (config == null) {
                    configure((String) getInitParameters().get(EXP_ATT_PARAM));
                }
            } catch (NoSuchElementException ex) {
                // parsing error
                return vmFromString(
                        Resources.getMessage("TLV_PARAMETER_ERROR",
                                EXP_ATT_PARAM));
            }

            // get a handler
            DefaultHandler h = getHandler();

            // parse the page
            XMLReader xmlReader = XmlUtil.newXMLReader(null);
            xmlReader.setContentHandler(h);
            InputStream inputStream = page.getInputStream();
            try {
                xmlReader.parse(new InputSource(inputStream));
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    // Suppressed.
                }
            }

            if (messageVector.size() == 0) {
                return null;
            } else {
                return vmFromVector(messageVector);
            }

        } catch (SAXException ex) {
            return vmFromString(ex.toString());
        } catch (IOException ex) {
            return vmFromString(ex.toString());
        } catch (ParserConfigurationException ex) {
            return vmFromString(ex.toString());
        }
    }

    //*********************************************************************
    // Protected utility functions

    // delegate validation to the appropriate expression language
    // TODO refactor this into EL tag specific functionality

    @Deprecated
    protected String validateExpression(
            String elem, String att, String expr) {

        return null;
    }

    // utility methods to help us match elements in our tagset

    protected boolean isTag(String tagUri,
                            String tagLn,
                            String matchUri,
                            String matchLn) {
        if (tagUri == null
                || tagUri.length() == 0
                || tagLn == null
                || matchUri == null
                || matchLn == null) {
            return false;
        }
        // match beginning of URI since some suffix *_rt tags can
        // be nested in EL enabled tags as defined by the spec
        if (tagUri.length() > matchUri.length()) {
            return (tagUri.startsWith(matchUri) && tagLn.equals(matchLn));
        } else {
            return (matchUri.startsWith(tagUri) && tagLn.equals(matchLn));
        }
    }

    protected boolean isJspTag(String tagUri, String tagLn, String target) {
        return isTag(tagUri, tagLn, JSP, target);
    }

    private boolean isTag(int type, String tagUri, String tagLn, String target) {
        return (this.tlvType == type && isTag(tagUri, tagLn, this.uri, target));
    }

    protected boolean isCoreTag(String tagUri, String tagLn, String target) {
        return isTag(TYPE_CORE, tagUri, tagLn, target);
    }

    protected boolean isFmtTag(String tagUri, String tagLn, String target) {
        return isTag(TYPE_FMT, tagUri, tagLn, target);
    }

    protected boolean isSqlTag(String tagUri, String tagLn, String target) {
        return isTag(TYPE_SQL, tagUri, tagLn, target);
    }

    protected boolean isXmlTag(String tagUri, String tagLn, String target) {
        return isTag(TYPE_XML, tagUri, tagLn, target);
    }

    // utility method to determine if an attribute exists

    protected boolean hasAttribute(Attributes a, String att) {
        return (a.getValue(att) != null);
    }

    /*
     * method to assist with failure [ as if it's not easy enough
     * already :-) ]
     */

    protected void fail(String message) {
        failed = true;
        messageVector.add(new ValidationMessage(lastElementId, message));
    }

    // returns true if the given attribute name is specified, false otherwise

    protected boolean isSpecified(TagData data, String attributeName) {
        return (data.getAttribute(attributeName) != null);
    }

    // returns true if the 'scope' attribute is valid

    protected boolean hasNoInvalidScope(Attributes a) {
        String scope = a.getValue(SCOPE);

        if ((scope != null)
                && !scope.equals(PAGE_SCOPE)
                && !scope.equals(REQUEST_SCOPE)
                && !scope.equals(SESSION_SCOPE)
                && !scope.equals(APPLICATION_SCOPE)) {
            return false;
        }

        return true;
    }

    // returns true if the 'var' attribute is empty

    protected boolean hasEmptyVar(Attributes a) {
        if ("".equals(a.getValue(VAR))) {
            return true;
        }
        return false;
    }

    // returns true if the 'scope' attribute is present without 'var'

    protected boolean hasDanglingScope(Attributes a) {
        return (a.getValue(SCOPE) != null && a.getValue(VAR) == null);
    }

    // retrieves the local part of a QName

    protected String getLocalPart(String qname) {
        int colon = qname.indexOf(":");
        if (colon == -1) {
            return qname;
        } else {
            return qname.substring(colon + 1);
        }
    }

    //*********************************************************************
    // Miscellaneous utility functions

    // parses our configuration parameter for element:attribute pairs

    private void configure(String info) {
        // construct our configuration map
        config = new HashMap();

        // leave the map empty if we have nothing to configure
        if (info == null) {
            return;
        }

        // separate parameter into space-separated tokens and store them
        StringTokenizer st = new StringTokenizer(info);
        while (st.hasMoreTokens()) {
            String pair = st.nextToken();
            StringTokenizer pairTokens = new StringTokenizer(pair, ":");
            String element = pairTokens.nextToken();
            String attribute = pairTokens.nextToken();
            Object atts = config.get(element);
            if (atts == null) {
                atts = new HashSet();
                config.put(element, atts);
            }
            ((Set) atts).add(attribute);
        }
    }

    // constructs a ValidationMessage[] from a single String and no ID

    static ValidationMessage[] vmFromString(String message) {
        return new ValidationMessage[]{
                new ValidationMessage(null, message)
        };
    }

    // constructs a ValidationMessage[] from a ValidationMessage Vector

    static ValidationMessage[] vmFromVector(Vector v) {
        ValidationMessage[] vm = new ValidationMessage[v.size()];
        for (int i = 0; i < vm.length; i++) {
            vm[i] = (ValidationMessage) v.get(i);
        }
        return vm;
    }
}
