// 
// The Waveset SPML General License 
// 
// Version 0.1, April 2003
// Copyright (C) 2003 Waveset Technologies, Inc..
// 6034 West Courtyard Drive, Suite 210, Austin, Texas 78730
// All rights reserved.
// 
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// 
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions, and the disclaimers in Sections 6
//    and 7 below.
// 
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the disclaimers in Sections 6
//    and 7 below in the documentation and/or other materials provided
//    with the distribution.
// 
// 3. The end-user documentation included with the redistribution, if
//    any, must include the following acknowledgment:
// 
//    "This product includes software developed by 
//     Waveset Technologies, Inc. (www.waveset.com)."
// 
//    Alternately, this acknowledgment may appear in the software itself, if
//    and wherever such third-party acknowledgments normally appear.
//  
// 4. The names "Waveset" and "Waveset Technologies, Inc." must not be
//    used to endorse or promote products derived from this software
//    without the prior written permission of Waveset. For written
//    permission, please contact www.waveset.com.
//  
// 5. Products derived from this software may not be called "Waveset",
//    nor may "Waveset" appear in their name, without the prior written
//    permission of Waveset.
//  
// 6. NO WARRANTY 
// 
//    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED
//    OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//    DISCLAIMED.
// 
// 7.  LIMITATION OF LIABILITY
// 
//    IN NO EVENT SHALL THE WAVESET OR ITS LICENSORS BE LIABLE FOR ANY
//    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
//    GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
//    IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
//    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 
// End of Terms and Conditions
// ====================================================================
//
// Component Name: org.openspml.message.BatchRequest
//
// Author(s): Jeff Larson
//
// Description:
//
// Class representing a "batch" of SpmlRequests.  Typically there
// will be only one, but the standard allows batches.
//
// Schema indiciates that the requests must be ordered as:
//   modifyRequest, addRequest, deleteRequest, extendedRequest
//
// I think we proably want to allow arbitrary ordering here rather
// than <xsd:sequence>.  This model will support arbitrary ordering.
//

package org.openspml.message;

import java.util.*;

import org.openspml.util.*;

/**
 * A class representing a collection of SPML requests to be executed
 * as a batch.
 * <p>
 * This contains a list of SpmlRequest objects, an indication of whether
 * parallel or serial execution is desired, and an indication of whether
 * the batch should continue after errors in one request.
 */
public class BatchRequest extends SpmlRequest implements Constants {

    //////////////////////////////////////////////////////////////////////
    //
    // Constants
    //
    //////////////////////////////////////////////////////////////////////

    static final String ELEMENT = "batchRequest";

    //
    // ProcessingType enumeration constants
    //

    public static final String PROC_SEQUENTIAL = 
    ENUM_PREFIX + "sequential";

    public static final String PROC_PARALLEL = 
    ENUM_PREFIX + "parallel";

    //
    // OnErrorType enumation constants
    //

    public static final String ON_ERROR_RESUME = 
    ENUM_PREFIX + "resume";

    public static final String ON_ERROR_EXIT = 
    ENUM_PREFIX + "exit";

    //////////////////////////////////////////////////////////////////////
    //
    // Fields
    //
    //////////////////////////////////////////////////////////////////////

    /**
     * List of SpmlRequest objects.
     */
    List _requests;

    /**
     * Optional list of Attribute objects that apply to the batch 
     * as a whole.
     */
    List _attributes;

    /**
     * True if parallel processing has been allowed.
     * The default is sequential.
     * This corresponds to the "processing" attributes.
     */
    boolean _parallel;

    /**
     * True if we continue processing other requests in the batch	
     * if one of them has an error.  Defaults to false.
     * This corresponds to the "onError" attribute.
     */
    boolean _onErrorResume;

    //////////////////////////////////////////////////////////////////////
    //
    // Constructors
    //
    //////////////////////////////////////////////////////////////////////

    /**
     * Create a new batch request.
     */
    public BatchRequest() {
    }

    BatchRequest(XmlElement e) {
	parseXml(e);
    }

    public SpmlResponse createResponse() {
        return new BatchResponse();
    }

    /**
     * Specify whether requests within the batch are to execute
     * serially or in parallel.  
     */
    public void setParallel(boolean b) {
	_parallel = b;
    }

    /**
     * Specify whether the batch should terminate as soon as one
     * request has an error, or whether the batch should continue.
     */
    public void setOnErrorResume(boolean b) {
	_onErrorResume = b;
    }

    /**
     * Set a collection of attribute that applies to the batch .
     */
    public void setAttributes(List l) {
        _attributes = l;
    }

    /**
     * Set one batch attribute.
     */
    public void setAttribute(Attribute a) {
        if (_attributes == null)
            _attributes = new ArrayList();
        _attributes.add(a);
    }
    
    /**
     * Set one batch attribute.
     */
    public void setAttribute(String name, Object value) {
        setAttribute(new Attribute(name, value));
    }

    /**
     * Set the list of requests.  The list must contain
     * <code>SpmlRequest</code> objects.
     */
    public void setRequests(List l) {
	_requests = l;
    }

    /**
     * Add one request to the batch.
     */
    public void addRequest(SpmlRequest r) {
	if (_requests == null)
	    _requests = new ArrayList();
	_requests.add(r);
    }

    //////////////////////////////////////////////////////////////////////
    //
    // Accessors
    //
    //////////////////////////////////////////////////////////////////////

    /**
     * Returns true if parallel execution is desired.
     */
    public boolean isParallel() {
	return _parallel;
    }

    /**
     * Returns true if the batch is to continue even if individual
     * requests have errors.
     */
    public boolean isOnErrorResume() {
	return _onErrorResume;
    }

    /**
     * Get the list of batch attributes.
     */
    public List getAttributes() {
	return _attributes;
    }

    /**
     * Get the list of requests in the batch.  The list will
     * contain <code>SpmlRequest</code> objects.
     */
    public List getRequests() {
	return _requests;
    }

    /**
     * Lookup a batch attribute by name.
     // More common to look for these by name than in other requests?
     // Assuming the list is short, otherwise use a HashMap.
     */
    public Attribute getAttribute(String name) {

	return Attribute.getAttribute(_attributes, name);
    }

    /**
     * Lookup a batch attribute by name.
     * The actual value of the attribute is returned, not
     * the Attribute object.
     */
    public Object getAttributeValue(String name) {
	return Attribute.getAttributeValue(_attributes, name);
    }

    //////////////////////////////////////////////////////////////////////
    //
    // XML
    //
    //////////////////////////////////////////////////////////////////////

    public String getElementName() {
        return ELEMENT;
    }

    void addSubclassAttributes(SpmlBuffer b) {

	if (_parallel)
	    b.addAttribute("processing", PROC_PARALLEL);
	else
	    b.addAttribute("processing", PROC_SEQUENTIAL);

	if (_onErrorResume)
	    b.addAttribute("onError", ON_ERROR_RESUME);
	else
	    b.addAttribute("onError", ON_ERROR_EXIT);
    }

    void addSubclassElements(SpmlBuffer b) {

	if (_requests != null) {
	    Iterator it = _requests.iterator();
	    while (it.hasNext()) {
		SpmlRequest req = (SpmlRequest)it.next();
		req.toXml(b);
	    }
	}

	Attribute.toXml(b, "batchAttributes", _attributes);
    }

    void parseXml(XmlElement e) {

        super.parseXml(e);

	String s = e.getAttribute("processing");
	_parallel = PROC_PARALLEL.equals(s);

	s = e.getAttribute("onError");
	_onErrorResume = ON_ERROR_RESUME.equals(s);

	for (XmlElement child = e.getChildElement() ; 
	     child != null ; child = child.next()) {

	    String tag = child.getLocalName();

	    if (tag.equals("batchAttributes"))
		_attributes = Attribute.parseList(child);
	    else {
                // may come back null if this is a common element
                SpmlRequest req = SpmlRequest.parseRequest(child);
                if (req != null)
                    addRequest(req);
            }
        }
    }


}

