/*
 * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.sql.rowset.spi;

import java.sql.SQLException;
import javax.sql.rowset.*;

/**
 * Indicates an error with the <code>SyncProvider</code> mechanism. This exception
 * is created by a <code>SyncProvider</code> abstract class extension if it
 * encounters violations in reading from or writing to the originating data source.
 * <P>
 * If it is implemented to do so, the <code>SyncProvider</code> object may also create a
 * <code>SyncResolver</code> object and either initialize the <code>SyncProviderException</code>
 * object with it at construction time or set it with the <code>SyncProvider</code> object at
 * a later time.
 * <P>
 * The method <code>acceptChanges</code> will throw this exception after the writer
 * has finished checking for conflicts and has found one or more conflicts. An
 * application may catch a <code>SyncProviderException</code> object and call its
 * <code>getSyncResolver</code> method to get its <code>SyncResolver</code> object.
 * See the code fragment in the interface comment for
 * <a href="SyncResolver.html"><code>SyncResolver</code></a> for an example.
 * This <code>SyncResolver</code> object will mirror the <code>RowSet</code>
 * object that generated the exception, except that it will contain only the values
 * from the data source that are in conflict.  All other values in the <code>SyncResolver</code>
 * object will be <code>null</code>.
 * <P>
 * The <code>SyncResolver</code> object may be used to examine and resolve
 * each conflict in a row and then go to the next row with a conflict to
 * repeat the procedure.
 * <P>
 * A <code>SyncProviderException</code> object may or may not contain a description of the
 * condition causing the exception.  The inherited method <code>getMessage</code> may be
 * called to retrieve the description if there is one.
 *
 * @author Jonathan Bruce
 * @see javax.sql.rowset.spi.SyncFactory
 * @see javax.sql.rowset.spi.SyncResolver
 * @see javax.sql.rowset.spi.SyncFactoryException
 */
public class SyncProviderException extends java.sql.SQLException {

    /**
     * The instance of <code>javax.sql.rowset.spi.SyncResolver</code> that
     * this <code>SyncProviderException</code> object will return when its
     * <code>getSyncResolver</code> method is called.
     */
     private SyncResolver syncResolver = null;

    /**
     * Creates a new <code>SyncProviderException</code> object without a detail message.
     */
    public SyncProviderException() {
        super();
    }

    /**
     * Constructs a <code>SyncProviderException</code> object with the specified
     * detail message.
     *
     * @param msg the detail message
     */
    public SyncProviderException(String msg)  {
        super(msg);
    }

    /**
     * Constructs a <code>SyncProviderException</code> object with the specified
     * <code>SyncResolver</code> instance.
     *
     * @param syncResolver the <code>SyncResolver</code> instance used to
     *     to process the synchronization conflicts
     * @throws IllegalArgumentException if the <code>SyncResolver</code> object
     *     is <code>null</code>.
     */
    public SyncProviderException(SyncResolver syncResolver)  {
        if (syncResolver == null) {
            throw new IllegalArgumentException("Cannot instantiate a SyncProviderException " +
                "with a null SyncResolver object");
        } else {
            this.syncResolver = syncResolver;
        }
    }

    /**
     * Retrieves the <code>SyncResolver</code> object that has been set for
     * this <code>SyncProviderException</code> object, or
     * if none has been set, an instance of the default <code>SyncResolver</code>
     * implementation included in the reference implementation.
     * <P>
     * If a <code>SyncProviderException</code> object is thrown, an application
     * may use this method to generate a <code>SyncResolver</code> object
     * with which to resolve the conflict or conflicts that caused the
     * exception to be thrown.
     *
     * @return the <code>SyncResolver</code> object set for this
     *     <code>SyncProviderException</code> object or, if none has
     *     been set, an instance of the default <code>SyncResolver</code>
     *     implementation. In addition, the default <code>SyncResolver</code>
     *     implementation is also returned if the <code>SyncResolver()</code> or
     *     <code>SyncResolver(String)</code> constructors are used to instantiate
     *     the <code>SyncResolver</code> instance.
     */
    public SyncResolver getSyncResolver() {
        if (syncResolver != null) {
            return syncResolver;
        } else {
            try {
              syncResolver = new com.sun.rowset.internal.SyncResolverImpl();
            } catch (SQLException sqle) {
            }
            return syncResolver;
        }
    }

    /**
     * Sets the <code>SyncResolver</code> object for this
     * <code>SyncProviderException</code> object to the one supplied.
     * If the argument supplied is <code>null</code>, a call to the method
     * <code>getSyncResolver</code> will return the default reference
     * implementation of the <code>SyncResolver</code> interface.
     *
     * @param syncResolver the <code>SyncResolver</code> object to be set;
     *     cannot be <code>null</code>
     * @throws IllegalArgumentException if the <code>SyncResolver</code> object
     *     is <code>null</code>.
     * @see #getSyncResolver
     */
    public void setSyncResolver(SyncResolver syncResolver) {
        if (syncResolver == null) {
            throw new IllegalArgumentException("Cannot set a null SyncResolver " +
                "object");
        } else {
            this.syncResolver = syncResolver;
        }
    }

    static final long serialVersionUID = -939908523620640692L;

}
