/*******************************************************************************
 * Copyright (c) 2001, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.j2ee.commonarchivecore.internal;



import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.emf.common.command.AbstractCommand;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jst.j2ee.internal.xml.CollectingErrorHandler;
import org.eclipse.jst.j2ee.internal.xml.XmlDocumentReader;
import org.xml.sax.InputSource;

/**
 * Insert the type's description here. Creation date: (03/19/01 10:04:08 AM)
 * 
 * @author: Administrator
 */
public class ValidateXmlCommand extends AbstractCommand {
	protected List results;
	protected ModuleFile archive;
	public boolean validateNested = true;

	/**
	 * ValidateXmlCommand constructor comment.
	 */
	protected ValidateXmlCommand() {
		super();
	}

	/**
	 * ValidateXmlCommand constructor comment.
	 * 
	 * @param label
	 *            java.lang.String
	 * @param description
	 *            java.lang.String
	 */
	public ValidateXmlCommand(ModuleFile m) {
		super();
		archive = m;
	}

	/**
	 * ValidateXmlCommand constructor comment.
	 * 
	 * @param label
	 *            java.lang.String
	 */
	protected ValidateXmlCommand(String label) {
		super(label);
	}

	/**
	 * ValidateXmlCommand constructor comment.
	 * 
	 * @param label
	 *            java.lang.String
	 * @param description
	 *            java.lang.String
	 */
	protected ValidateXmlCommand(String label, String description) {
		super(label, description);
	}

	/**
	 * @see Command
	 */
	public void execute() {
		results = new ArrayList();
		validatateXml();
		if (isValidateNested()) {
			List archives = archive.getArchiveFiles();
			for (int i = 0; i < archives.size(); i++) {
				Archive a = (Archive) archives.get(i);
				if (!a.isModuleFile())
					continue;
				ModuleFile m = (ModuleFile) a;
				ValidateXmlCommand cmd = new ValidateXmlCommand(m);
				cmd.execute();
				results.addAll(cmd.getResult());
			}
		}
	}

	/**
	 * @return List of XmlValidationResult; 1 for the archive, and one for each nested module file
	 */
	public Collection getResult() {
		return results;
	}

	/**
	 * Insert the method's description here. Creation date: (10/22/2001 1:06:52 PM)
	 * 
	 * @return boolean
	 */
	public boolean isValidateNested() {
		return validateNested;
	}

	protected boolean prepare() {
		return true;
	}

	/**
	 * @see Command
	 */
	public void redo() {
		//Default
	}

	/**
	 * Insert the method's description here. Creation date: (10/22/2001 1:06:52 PM)
	 * 
	 * @param newValidateNested
	 *            boolean
	 */
	public void setValidateNested(boolean newValidateNested) {
		validateNested = newValidateNested;
	}

	protected void validatateXml() {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		Resource res = archive.getStandardDeploymentDescriptor().eResource();
		XmlValidationResult result = new XmlValidationResult();
		result.setArchive(archive);
		try {
			res.save(bos, new java.util.HashMap());
		} catch (Exception ex) {
			throw new org.eclipse.jst.j2ee.commonarchivecore.internal.exception.ArchiveRuntimeException(ex);
		}
		ByteArrayInputStream inStream = new ByteArrayInputStream(bos.toByteArray());
		InputSource source = new InputSource(inStream);
		CollectingErrorHandler handler = new CollectingErrorHandler();
		XmlDocumentReader parseAdapter = new XmlDocumentReader(source, null, handler);

		// the following try/catch clause is added to handle the case
		// when SAX parser throws a fatal exception (type SAXException)
		// for unmatching end tag that results in a RuntimeException to
		// be thrown. Need to catch it so we can get the parser exceptions
		// and display them to the user.
		try {
			parseAdapter.parseDocument();
		} catch (RuntimeException re) {

			if (handler.getCaughtExceptions() != null) {
				result.setArchive(archive);
				result.setCaughtExceptions(handler.getCaughtExceptions());
				results.add(result);
			}

			throw re;
		}

		result.setArchive(archive);
		result.setCaughtExceptions(handler.getCaughtExceptions());
		results.add(result);
	}
}
