/* Copyright (c) 2003, Oracle Corporation. All Rights Reserved. */
package oracle.portal.provider.v2.utils;

import oracle.webdb.utils.SimpleStringBuffer;

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

/**
 * A <code>ValidationError</code> maintains a list of {@link
 * ValidationError.Error}s reported by a tree of {@link
 * oracle.portal.provider.v2.Validateable} objects during validation
 * traversal.<p>
 *
 * Context information, such as the location within a tree of objects, is
 * supplied using the utility {@link #newContext(String, String, String)}
 * method.
 */
public class ValidationError
{
    private static final String CONTEXT_DELIM = " > ";
    private List mErrors = new ArrayList(10);

    /**
     * Constructs this <code>ValidationError</code> instance.
     */
    public ValidationError()
    {
    }

    /**
     * Adds an error to the list maintained by this
     * <code>ValidationError</code> instance. The context information supplied
     * should conatin the context information of entities calling the current
     * {@link oracle.portal.provider.v2.Validateable}. This will be the case if
     * the utility {@link #newContext(String, String, String)} was used.
     *
     * @param context Current context information.
     * @param message The error message.
     * @param values The error values.
     */
    public void addError(String context, String message, String values)
    {
        Error error = new Error(context, message, values);
        mErrors.add(error);
    }

    /**
     * Returns a <code>java.util.Iterator</code> providing ordered retrieval of
     * the {@link ValidationError.Error}s entered into this
     * <code>ValidationError</code> instance.
     *
     * @return a <code>java.util.Iterator</code> whose members are of type
     * {@link ValidationError.Error}.
     */
    public Iterator iterator()
    {
        return mErrors.iterator();
    }

    /**
     * Indicates whether or not this <code>ValidationError</code> instance is
     * currently empty.
     *
     * @return a <code>boolean</code> flag.
     */
    public boolean isEmpty()
    {
        return mErrors.isEmpty();
    }

    /**
     * Returns a <code>java.lang.String</code> representation of this
     * <code>ValidationError</code> instance.
     */
    public String toString()
    {
        if (isEmpty())
        {
            return null;
        }
        SimpleStringBuffer buff = new SimpleStringBuffer(500);
        Iterator it = mErrors.iterator();
        Error error = null;
        String values = null;
        while (it.hasNext())
        {
            error = (Error)it.next();
            buff.append(error.getContext()).append(' ');
            buff.append(error.getError()).append(' ');
            values = error.getValues();
            if (values != null)
            {
                buff.append(values);
            }
            buff.append("\n");
        }
        return buff.toString();
    }

    /**
     * Returns a new context string containing the parent context and current
     * context delimited by a &quot;&gt;&quot character. The current context is
     * constructed from the supplied object type name and object instance name
     * (if any).
     *
     * @param parentContext The parent context.
     * @param typeName The type name of the current {@link
     * oracle.portal.provider.v2.Validateable} instance.
     * @param objName The instance name of the current {@link
     * oracle.portal.provider.v2.Validateable} instance.
     * @return a new context string or <code>null</code> if it was not possible
     * t construct one from the supplied information.
     */
    public static String newContext(String parentContext, String typeName,
                                    String objName)
    {
        SimpleStringBuffer newContext = new SimpleStringBuffer(100);
        if (parentContext != null && parentContext.length() > 0)
        {
            newContext.append(parentContext).append(CONTEXT_DELIM);
        }
        if (typeName != null && typeName.length() > 0)
        {
            newContext.append(typeName);
        }
        else
        {
            newContext.append("Unknown Type");
        }
        if (objName != null && objName.length() > 0)
        {
            newContext.append('(').append(objName).append(')');
        }
        return (newContext.length() > 0 ? newContext.toString() : null);
    }

    /**
     * Encapsulates information relating to a single error.
     */
    public static class Error
    {
        private String mContext = null;
        private String mError = null;
        private String mValues = null;

        /**
         * Constructs this <code>Error</code> instance with the supplied
         * context and error details.
         *
         * @param context Context information.
         * @param error Error message.
         * @param values Error values.
         */
        public Error(String context, String error, String values)
        {
            mContext = context;
            mError = error;
            mValues = values;
        }

        /**
         * Returns the context of this <code>Error</code>.
         */
        public String getContext()
        {
            return mContext;
        }

        /**
         * Returns the reason for this <code>Error</code>.
         */
        public String getError()
        {
            return mError;
        }

        /**
         * Returns the values of this <code>Error</code>.
         */
        public String getValues()
        {
            return mValues;
        }
    }

}
