/*******************************************************************************
 * Copyright (c) 2006 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
 * 
 *      
 *******************************************************************************/
package org.eclipse.callisto.tools.versionchecker;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.core.runtime.IPlatformRunnable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.update.configurator.ConfiguratorUtils;
import org.eclipse.update.configurator.IPlatformConfiguration;
import org.eclipse.update.configurator.IPlatformConfiguration.IFeatureEntry;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * 
 * A simple, unsupported, little-tested utility to check version numbers of
 * currently installed plugins against a reference list that was previously
 * prepared by running this utility on some earlier installed stack.
 * 
 */
public class VersionLister implements IPlatformRunnable {

	private static final String REFERENCE_VERSIONING_DATA_XML = "referenceVersioningData.xml";

	private static final String VERSION_CHECKER_BUNDLE_NAME = "org.eclipse.callisto.tools.versionchecker";

	private static final String EOL = System.getProperty("line.separator");

	private static final String[] alwaysExclude = new String[]{"org.eclipse.releng.tools", "org.tigris.mm.ui", "org.eclipse.core.resources.spysupport", "com.yourkit.profiler", "org.eclipse.core.tools.resources", "org.eclipse.core.tools", "org.eclipse.callisto.tools.versionchecker"};
	private static final String[] alwaysExcludeFeatures = new String[]{"org.eclipse.releng.tools", "org.eclipse.test"};
	private static final String[] interestingPatterns = new String[]{"org.eclipse.wst", "org.eclipse.jst", "org.eclipse.jem", "org.eclipse.jpt", "org.eclipse.atf"};

	private static final int HELP = 0;
	private static final String HELP_ARG = "-help";

	private static final int LIST_TO_CONSOLE = 1;
	private static final String LIST_TO_CONSOLE_ARG = "-listToReferenceFile";

	private static final int TEST_TO_REFERENCE = 2;
	private static final String TEST_TO_REFERENCE_ARG = "-testToReference";

	private static final int COUNT_QUALIFIER_ONLY_AS_ERROR_CODE = 3;

	private static final int MAJOR = 0;
	private static final int MINOR = 1;
	private static final int SERVICE = 2;
	private static final int QUALIFIER = 3;

	private static final String BUNDLE_DATA = "bundleData";

	private static final String FEATURE_DATA = "featureData";

	private static final int ERROR_BASE_CODE = 90000;
	private static final int ERROR_BUNDLE_DECREASE = 0x0001;
	private static final int ERROR_FEATURE_DECREASE = 0x0010;
	private static final int ERROR_EXCEPTION_OCCURRED = 0x0100;
	private static final int ERROR_QUALIFIER_ONLY_INCREAASE = 0x1000;
	private static final int TEST_TO_REFERENCE_ID_NOT_FOUND = 0x00010000;
	private static final Object OK_EXIT = IPlatformRunnable.EXIT_OK;

	private static final String COUNT_QUALIFIER_ONLY_AS_ERROR = "countQualifierIncreaseOnlyAsError";
	private boolean countQualifierOnlyAsError;

	public VersionLister() {
	}

	public static void main(String[] args) {
		// for quick tests, only
		VersionLister versionLister = new VersionLister();
		versionLister.clean("M-testing-123");
	}

	public Object run(Object o) throws Exception {

		int exitResult = ERROR_BASE_CODE;
		String args[] = null;
		if (o instanceof String[]) {
			args = (String[]) o;
		}
		else {
			doPrintHelp();
			return OK_EXIT;
		}

		printArgs(args);
		// printProperties();

		if (args.length == 0) {
			exitResult = exitResult | doPrintHelp();
		}
		else {
			boolean someCommandExecuted = false;
			for (int i = 0; i < args.length; i++) {
				String arg = args[i].trim();
				System.out.println("command: " + arg);
				switch (getCommand(arg)) {
					case LIST_TO_CONSOLE : {
						// System.out.println(" executing list to console");
						String xmlId = null;
						int idPos = i + 1;
						if (idPos < args.length) {
							String possibleId = args[idPos];
							// sanity check just not another command
							if (!possibleId.startsWith("-")) {
								xmlId = possibleId;
							}
							else {
								xmlId = getDefaultID();
							}
						}
						else {
							xmlId = getDefaultID();
						}

						exitResult = exitResult | doListCurrentToConsole(xmlId);

						someCommandExecuted = true;
						break;
					}
					case TEST_TO_REFERENCE : {
						// System.out.println(" executing test to reference");
						String referenceId = "WTPSDK";
						String referenceFilename = REFERENCE_VERSIONING_DATA_XML;
						int idPos = i + 1;
						if (idPos < args.length) {
							String possibleId = args[idPos];
							// sanity check just not another command
							if (!possibleId.startsWith("-")) {
								referenceId = possibleId;
							}
						}
						idPos++;
						if (idPos < args.length) {
							String possibleFilename = args[idPos];
							// sanity check just not another command
							if (!possibleFilename.startsWith("-")) {
								referenceFilename = possibleFilename;
							}
						}


						String buildLabel = System.getProperty("buildLabel");
						if (buildLabel != null && buildLabel.length() != 0) {
							// leave buildLabel as found, for here (may adjust
							// later)
						}
						else {
							buildLabel = "NoBuildLabel";
						}
						someCommandExecuted = true;
						exitResult = exitResult | doTestToReference(referenceId, referenceFilename, buildLabel);

						// minor error in arguments
						if (!someCommandExecuted) {
							exitResult = exitResult | doPrintHelp();
						}
						break;
					}
					case COUNT_QUALIFIER_ONLY_AS_ERROR_CODE : {
						countQualifierOnlyAsError = true;
						break;
					}
					case HELP : {
						exitResult = exitResult | doPrintHelp();
						someCommandExecuted = true;
						break;
					}
					default : {
						/* do nothing, since in a loop */
						break;
					}
				}
			}
			if (!someCommandExecuted) {
				exitResult = exitResult | doPrintHelp();
			}
		}
		Object result = IPlatformRunnable.EXIT_OK;
		if (exitResult > ERROR_BASE_CODE) {
			result = new Integer(exitResult);
		}
		return result;
	}

	void printArgs(String[] args) {
		System.out.println("\t Program Arguments: ");
		for (int i = 0; i < args.length; i++) {
			System.out.println("\t\t" + args[i]);
		}

	}

	void printProperties() {
		Properties properties = System.getProperties();
		properties.list(System.out);
	}

	private int doTestToReference(String id, String referenceFileName, String currentId) {
		int exit_code = ERROR_BASE_CODE;


		try {
			Map refMap = getReferenceBundleMap(id, referenceFileName);
			// will be null if no ID found.
			if (refMap != null) {
				String outputFileName = "versioningReport";
				File outfile = createOutputFile(outputFileName);
				Writer reportWriter = new FileWriter(outfile);
				reportWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + EOL);

				reportWriter.write("<versioningReport>" + EOL);
				reportWriter.write("<versioningReportData id=\"" + id + "\"" + " current=\"" + clean(currentId) + "\"" + ">" + EOL);

				Map currMap = makeBundleMap();
				String checkingType = "bundle";
				int bundle_return = _compareReferenceAndCurrent(currMap, refMap, checkingType, ERROR_BUNDLE_DECREASE, reportWriter);
				exit_code = exit_code | bundle_return;

				refMap = getReferenceFeatureMap(id, referenceFileName);
				currMap = makeFeatureMap();
				checkingType = "feature";
				int feature_return = _compareReferenceAndCurrent(currMap, refMap, checkingType, ERROR_FEATURE_DECREASE, reportWriter);
				exit_code = exit_code | feature_return;

				reportWriter.write("</versioningReportData>" + EOL);
				reportWriter.write("</versioningReport>" + EOL);

				System.out.println("Note: versioning report written to " + outfile.getAbsolutePath());
				reportWriter.close();


			}
			else {
				System.out.println("No reference ID found named " + id);
				exit_code = exit_code | TEST_TO_REFERENCE_ID_NOT_FOUND;
			}
		}
		catch (ParserConfigurationException e) {
			e.printStackTrace();
			exit_code = exit_code & ERROR_EXCEPTION_OCCURRED;
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
			exit_code = exit_code & ERROR_EXCEPTION_OCCURRED;
		}
		catch (SAXException e) {
			e.printStackTrace();
			exit_code = exit_code & ERROR_EXCEPTION_OCCURRED;
		}

		catch (IOException e) {
			e.printStackTrace();
			exit_code = exit_code & ERROR_EXCEPTION_OCCURRED;
		}

		return exit_code;
	}

	private File createOutputFile(String outputFileName) throws IOException {
		File outputDirectory = null;
		String outputDirName = System.getProperty("buildDirectory");
		String dirLabel = System.getProperty("buildLabel");
		if (outputDirName != null && outputDirName.length() > 0) {
			if (dirLabel != null && dirLabel.length() > 0) {
				outputDirectory = new File(outputDirName + "/" + dirLabel);
			}
		}
		String localOutputFilename = null;
		String outputFileNameSuffix = System.getProperty("buildLabel");
		if (outputFileNameSuffix != null) {
			localOutputFilename = outputFileName + "_" + clean(outputFileNameSuffix) + ".xml";
		}
		else {
			localOutputFilename = outputFileName + ".xml";
		}
		File outfile = new File(outputDirectory, localOutputFilename);

		return outfile;
	}

	private int _compareReferenceAndCurrent(Map currMap, Map refMap, String checkingType, int errorExitCode, Writer reportWriter) throws IOException {

		String reportExtraInCurrentResult = "extraInCurrent";
		String reportExtraInReferenceResult = "extraInReference";


		// return zero for success
		int result = 0;
		List extrasInCurrent = compareKeys(currMap, refMap);
		if (extrasInCurrent.size() > 0) {
			Object[] extras = extrasInCurrent.toArray();
			for (int i = 0; i < extras.length; i++) {
				String key = (String) extras[i];
				if (isInteresting(key)) {
					Version refVersion = (Version) refMap.get(key);
					_printExtra(key, refVersion, checkingType, reportExtraInCurrentResult, reportWriter);
				}
			}
		}
		List extrasInReferences = compareKeys(refMap, currMap);
		if (extrasInReferences.size() > 0) {
			Object[] extras = extrasInReferences.toArray();
			for (int i = 0; i < extras.length; i++) {
				String key = (String) extras[i];
				if (isInteresting(key)) {
					Version curVersion = (Version) currMap.get(key);
					_printExtra(key, curVersion, checkingType, reportExtraInReferenceResult, reportWriter);
				}
			}
		}

		// now for the version compares -- first, look for errors
		Iterator currentIterator = currMap.keySet().iterator();
		while (currentIterator.hasNext()) {
			String key = (String) currentIterator.next();
			if (isInteresting(key)) {
				Version refVersion = (Version) refMap.get(key);
				Version curVersion = (Version) currMap.get(key);
				if ((refVersion != null) && (curVersion != null) && !curVersion.getQualifier().equals("HEAD")) {
					int comp = refVersion.compareTo(curVersion);
					if (comp > 0) {
						/*
						 * if wrong, always print as error in summary
						 */
						_printError(key, refVersion, curVersion, checkingType, reportWriter);
						/*
						 * but only count as error for return code (and hence
						 * JUnit tests) if in our include list
						 */
						if (isInteresting(key)) {
							result = errorExitCode;
						}
					}
				}
			}
		}

		// now for the version compares -- first for MAJOR changes
		Iterator currentIterator2 = currMap.keySet().iterator();
		while (currentIterator2.hasNext()) {

			checkDifference(refMap, currMap, currentIterator2, MAJOR, checkingType, reportWriter);
		}
		Iterator currentIterator2a = currMap.keySet().iterator();
		while (currentIterator2a.hasNext()) {

			checkDifference(refMap, currMap, currentIterator2a, MINOR, checkingType, reportWriter);
		}
		Iterator currentIterator2b = currMap.keySet().iterator();
		while (currentIterator2b.hasNext()) {

			checkDifference(refMap, currMap, currentIterator2b, SERVICE, checkingType, reportWriter);
		}
		Iterator currentIterator2c = currMap.keySet().iterator();
		while (currentIterator2c.hasNext()) {
			int qualifierCount = 0;
			qualifierCount = checkDifference(refMap, currMap, currentIterator2c, QUALIFIER, checkingType, reportWriter);
			if (qualifierCount > 0 && countQaulifierOnlyAsError()) {
				result = result + ERROR_QUALIFIER_ONLY_INCREAASE;
			}
		}

		// just as well list unchanged ones for completeness!
		Iterator currentIterator3 = currMap.keySet().iterator();
		while (currentIterator3.hasNext()) {
			String key = (String) currentIterator3.next();
			if (isInteresting(key)) {

				Version refVersion = (Version) refMap.get(key);
				Version curVersion = (Version) currMap.get(key);
				if ((refVersion != null) && (curVersion != null)) {
					int comp = refVersion.compareTo(curVersion);
					if (comp == 0) {
						_printNoChange(key, refVersion, curVersion, checkingType, reportWriter);
					}
				}
			}
		}

		return result;
	}

	private boolean countQaulifierOnlyAsError() {
		boolean result = false;
		// let system property rule, if it is defined, else use argument given
		// us at start
		String property = System.getProperty(COUNT_QUALIFIER_ONLY_AS_ERROR);
		if (property != null && property.length() > 0) {
			if ("true".equals(property)) {
				result = true;
			}
		} else {
			result = countQualifierOnlyAsError;
		}
		return result;
	}

	/**
	 * @param key
	 * @return
	 */
	private boolean isInteresting(String key) {
		boolean result = false;

		for (int i = 0; i < interestingPatterns.length; i++) {
			if (key.startsWith(interestingPatterns[i])) {
				result = true;
				break;
			}
		}
		return result;
	}

	private int checkDifference(Map refMap, Map currMap, Iterator iterator, int fieldToCheck, String checkingType, Writer reportWriter) throws IOException {
		int result = 0;
		String key = (String) iterator.next();
		if (isInteresting(key)) {

			Version refVersion = (Version) refMap.get(key);
			Version curVersion = (Version) currMap.get(key);
			if ((refVersion != null) && (curVersion != null)) {
				int comp = refVersion.compareTo(curVersion);
				if (comp < 0) {
					if (fieldToCheck == MAJOR) {
						if (refVersion.getMajor() < curVersion.getMajor()) {
							_printIncrease(key, refVersion, curVersion, "major", checkingType, reportWriter);
							// if found, remove so no need to have complicated
							// check for minor, service, etc.
							iterator.remove();
						}
					}
					else if (fieldToCheck == MINOR) {
						if (refVersion.getMinor() < curVersion.getMinor()) {
							_printIncrease(key, refVersion, curVersion, "minor", checkingType, reportWriter);
							// if found, remove so no need to have complicated
							// check for minor, service, etc.
							iterator.remove();
						}
					}
					else if (fieldToCheck == SERVICE) {
						if (refVersion.getMicro() < curVersion.getMicro()) {
							_printIncrease(key, refVersion, curVersion, "service", checkingType, reportWriter);
							// if found, remove so no need to have complicated
							// check for minor, service, etc.
							iterator.remove();
						}
					}
					else if (fieldToCheck == QUALIFIER) {
						// skip test if doing "HEAD Build"
						System.out.println("curVersion: " + curVersion.getQualifier());
						if (!curVersion.getQualifier().equals("HEAD")) {
							if (refVersion.compareTo(curVersion) < 0) {
								result++;
								_printIncrease(key, refVersion, curVersion, "qualifier", checkingType, reportWriter);
							}
						}
						else {
							System.out.println("curVersion qualifier was HEAD");
						}
						// not sure his last one has to be removed
						iterator.remove();
					}
				}
			}
		}
		return result;
	}

	private void _printIncrease(String key, Version refVersion, Version curVersion, String field, String codePackageType, Writer reportWriter) throws IOException {
		String name = key.trim();
		String reportResult = "increase";
		reportWriter.write("<versioningCompare kind=\"" + reportResult + "\"" + " field=\"" + field + "\"" + " codePackageType=\"" + codePackageType + "\"" + ">" + EOL);
		reportWriter.write("\t" + "<entry>" + EOL + "\t\t" + name + EOL + "\t" + "</entry>" + EOL);
		reportWriter.write("\t" + "<reference>" + EOL + "\t\t" + refVersion + EOL + "\t" + "</reference>" + EOL);
		reportWriter.write("\t" + "<current>" + EOL + "\t\t" + curVersion + EOL + "\t" + "</current>" + EOL);
		reportWriter.write("</versioningCompare>" + EOL);
	}

	private void _printNoChange(String key, Version refVersion, Version curVersion, String codePackageType, Writer reportWriter) throws IOException {
		String name = key.trim();
		String reportResult = "noChange";
		reportWriter.write("<versioningCompare kind=\"" + reportResult + "\"" + " codePackageType=\"" + codePackageType + "\"" + ">" + EOL);
		reportWriter.write("\t" + "<entry>" + EOL + "\t\t" + name + EOL + "\t" + "</entry>" + EOL);
		reportWriter.write("\t" + "<reference>" + EOL + "\t\t" + refVersion + EOL + "\t" + "</reference>" + EOL);
		reportWriter.write("\t" + "<current>" + EOL + "\t\t" + curVersion + EOL + "\t" + "</current>" + EOL);
		reportWriter.write("</versioningCompare>" + EOL);
	}

	private void _printError(String key, Version refVersion, Version curVersion, String codePackageType, Writer reportWriter) throws IOException {
		String name = key.trim();
		String reportResult = "error";
		reportWriter.write("<versioningCompare kind=\"" + reportResult + "\" codePackageType=\"" + codePackageType + "\"" + ">" + EOL);
		reportWriter.write("\t" + "<entry>" + EOL + "\t\t" + name + EOL + "\t" + "</entry>" + EOL);
		reportWriter.write("\t" + "<reference>" + EOL + "\t\t" + refVersion + EOL + "\t" + "</reference>" + EOL);
		reportWriter.write("\t" + "<current>" + EOL + "\t\t" + curVersion + EOL + "\t" + "</current>" + EOL);
		reportWriter.write("</versioningCompare>" + EOL);
	}

	private void _printExtra(String key, Version version, String codePackageType, String reportResult, Writer reportWriter) throws IOException {
		String name = key.trim();
		reportWriter.write("<versioningCompare kind=\"" + reportResult + "\" codePackageType=\"" + codePackageType + "\"" + ">" + EOL);
		reportWriter.write("\t" + "<entry>" + EOL + "\t\t" + name + EOL + "\t" + "</entry>" + EOL);
		reportWriter.write("\t" + "<reference>" + EOL + "\t\t" + version + EOL + "\t" + "</reference>" + EOL);
		reportWriter.write("</versioningCompare>" + EOL);
	}

	private List compareKeys(Map baseMap, Map compareMap) {
		List extras = new ArrayList();

		Iterator iterator = compareMap.keySet().iterator();
		while (iterator.hasNext()) {
			String key = (String) iterator.next();
			if (!baseMap.containsKey(key)) {
				extras.add(key);
			}
		}
		return extras;
	}

	private Map getReferenceBundleMap(String id, String referenceFileName) throws FactoryConfigurationError, ParserConfigurationException, FileNotFoundException, SAXException, IOException {

		SortedMap refSortedMap = null;
		Document dom = getReferenceDataDOM(referenceFileName);

		Element refereneDataElement = dom.getElementById(id);
		if (refereneDataElement != null) {
			NodeList childNodes = refereneDataElement.getElementsByTagName(BUNDLE_DATA);
			Element bundleElement = (Element) childNodes.item(0);

			childNodes = bundleElement.getChildNodes();

			refSortedMap = new TreeMap();
			_extractEntryList(refSortedMap, childNodes);
		}
		else {
			System.out.println("no ref id");
		}
		return refSortedMap;
	}

	private Map getReferenceFeatureMap(String id, String referenceFileName) throws FactoryConfigurationError, ParserConfigurationException, FileNotFoundException, SAXException, IOException {

		Document dom = getReferenceDataDOM(referenceFileName);

		Element refereneDataElement = dom.getElementById(id);
		NodeList childNodes = refereneDataElement.getElementsByTagName(FEATURE_DATA);
		Element bundleElement = (Element) childNodes.item(0);

		childNodes = bundleElement.getChildNodes();

		SortedMap refSortedMap = new TreeMap();
		_extractEntryList(refSortedMap, childNodes);

		return refSortedMap;
	}

	private Document getReferenceDataDOM(String referenceFileName) throws ParserConfigurationException, IOException, SAXException {
		Document dom = null;
		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
		documentBuilderFactory.setValidating(true);
		documentBuilderFactory.setIgnoringElementContentWhitespace(true);
		documentBuilderFactory.setIgnoringComments(true);
		DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
		Bundle versionCheckerBundle = Platform.getBundle(VERSION_CHECKER_BUNDLE_NAME);
		URL referenceDataURL = versionCheckerBundle.getResource(referenceFileName);
		if (referenceDataURL != null) {
			InputStream inStream = referenceDataURL.openStream();
			InputSource is = new InputSource(inStream);
			documentBuilder.setEntityResolver(new ClassPathResolver());
			dom = documentBuilder.parse(is);
		}
		else {
			System.out.println("Program Error: Could not find reference file: " + referenceFileName);
		}
		return dom;
	}

	private void _extractEntryList(SortedMap refSortedMap, NodeList childNodes) {
		int nNodes = childNodes.getLength();


		for (int i = 0; i < nNodes; i++) {
			Element entry = (Element) childNodes.item(i);
			Node name = entry.getElementsByTagName("name").item(0);
			Node version = entry.getElementsByTagName("version").item(0);
			String bundleName = getTextContent(name);
			String versionString = getTextContent(version);

			refSortedMap.put(bundleName, new Version(versionString));
		}
	}

	/**
	 * A convenience method for DOM2, that should behave as
	 * node.getTextContent in DOM3.
	 * 
	 * @param node
	 * @return the string of the text node, or consequtive text nodes, that
	 *         are children of node. If there are no children, the empty
	 *         string is returned.
	 */
	private String getTextContent(Node node) {
		StringBuffer buffer = new StringBuffer();
		NodeList childNodes = node.getChildNodes();
		for (int i = 0; i < childNodes.getLength(); i++) {
			Node textNode = childNodes.item(i);
			if (textNode.getNodeType() == Node.TEXT_NODE) {
				buffer.append(cleanWhiteSpace(textNode.getNodeValue()));
			}
			else {
				// break out at first occurrence of non text node, if any
				break;
			}
		}
		return buffer.toString();
	}

	private int doPrintHelp() {
		int exitCode = ERROR_BASE_CODE;
		System.out.println();
		System.out.println("\tto use VersionChecker, include one of the following commands: ");
		System.out.println("\t\t" + LIST_TO_CONSOLE_ARG);
		System.out.println("\t\t" + TEST_TO_REFERENCE_ARG + " refId " + "[referenceDataFilename]");
		System.out.println();

		return exitCode;


	}

	private int getCommand(String arg) {
		int result = -1;

		if (HELP_ARG.equalsIgnoreCase(arg)) {
			result = HELP;
		}
		else if (LIST_TO_CONSOLE_ARG.equalsIgnoreCase(arg)) {
			result = LIST_TO_CONSOLE;
		}
		else if (TEST_TO_REFERENCE_ARG.equalsIgnoreCase(arg)) {
			result = TEST_TO_REFERENCE;
		}
		else if (COUNT_QUALIFIER_ONLY_AS_ERROR.equalsIgnoreCase(arg)) {
			result = COUNT_QUALIFIER_ONLY_AS_ERROR_CODE;
		}

		return result;
	}


	private Map makeFeatureMap() {
		IPlatformConfiguration config = ConfiguratorUtils.getCurrentPlatformConfiguration();
		IFeatureEntry[] features = config.getConfiguredFeatureEntries();


		SortedMap sortedMap = new TreeMap();
		for (int i = 0; i < features.length; i++) {
			String name = features[i].getFeatureIdentifier();
			name = name.trim();
			String versionString = features[i].getFeatureVersion();
			Version version = new Version(versionString);

			if (!contains(name, alwaysExcludeFeatures)) {
				sortedMap.put(name, version);


				// in case it already contains one, we need to make sure we
				// keep
				// only the highest one, as it would be resolved at runtime.
				Version possibleVersion = (Version) sortedMap.get(name);
				// if none, we can simply put in what we have
				if (possibleVersion == null) {
					sortedMap.put(name, version);
				}
				else {
					int comp = version.compareTo(possibleVersion);
					if (comp > 0) {
						// new one is higher, so put it in, else
						// it's fine the way it is
						sortedMap.put(name, possibleVersion);
					}
				}
			}
		}
		return sortedMap;
	}


	private int doListCurrentToConsole(String xmlId) throws IOException {

		int exitResult = ERROR_BASE_CODE;
		String outputFileName = "versioningReference";
		File outputFile = createOutputFile(outputFileName);
		Writer referenceWriter = new FileWriter(outputFile);

		// TODO: needs to really write UTF-8, or better, serialize DOM
		referenceWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + EOL);

		referenceWriter.write("<versioningData>" + EOL);

		referenceWriter.write("<referenceData id=\"" + xmlId + "\">" + EOL);


		Map featureMap = makeFeatureMap();
		referenceWriter.write("<featureData>" + EOL);
		referenceWriter.write("<!-- Number of features: " + featureMap.size() + " -->" + EOL);
		referenceWriter.write(EOL);

		_producePrintedPairs(featureMap, referenceWriter);

		referenceWriter.write("</featureData>" + EOL);



		Map bundleMap = makeBundleMap();

		referenceWriter.write("<bundleData>" + EOL);
		referenceWriter.write("<!-- Number of bundles: " + bundleMap.size() + " -->" + EOL);

		referenceWriter.write(EOL);

		_producePrintedPairs(bundleMap, referenceWriter);

		referenceWriter.write("</bundleData>" + EOL);


		referenceWriter.write("</referenceData>" + EOL);
		referenceWriter.write("</versioningData>" + EOL);

		System.out.println("Note: versioning reference data written to " + outputFile.getAbsolutePath());
		referenceWriter.close();

		return exitResult;
	}

	/**
	 * @return
	 */
	private String getCurrentInstallPath() {
		Location installLocation = Platform.getInstallLocation();
		URL installLoc = installLocation.getURL();
		String installLocationString = "no install location!?";
		if (installLoc != null) {
			installLocationString = installLoc.getPath();
		}
		return installLocationString;
	}

	private String getDefaultID() {
		String defaultID = null;
		String buildLabel = System.getProperty("buildLabel");
		if (buildLabel != null && buildLabel.length() != 0) {
			defaultID = clean(buildLabel);
		}
		else {
			defaultID = getCurrentInstallPath();
		}
		return defaultID;
	}

	private void _producePrintedPairs(Map map, Writer referenceWriter) throws IOException {
		Set referenceKeySet = map.keySet();
		Iterator refIterator = referenceKeySet.iterator();
		while (refIterator.hasNext()) {
			String name = (String) refIterator.next();
			Version version = (Version) map.get(name);
			name = name.trim();
			referenceWriter.write("<entry>" + EOL);
			referenceWriter.write("\t" + "<name>" + name + "</name>" + EOL);
			referenceWriter.write("\t" + "<version>" + version + "</version>" + EOL);
			referenceWriter.write("</entry>" + EOL);
		}
		return;
	}

	private Map makeBundleMap() {
		BundleDescription bundles[] = Platform.getPlatformAdmin().getState().getBundles();

		SortedMap sortedMap = new TreeMap();
		for (int i = 0; i < bundles.length; i++) {
			String bundleName = bundles[i].getName();
			Version bundleVersion = bundles[i].getVersion();
			System.out.println(bundleName + "\t\t\t" + bundleVersion);
			bundleName = bundleName.trim();
			if (!contains(bundleName, alwaysExclude)) {
				// in case it already contains one, we need to make sure we
				// keep
				// only the highest one, as it would be resolved at runtime.
				Version possibleVersion = (Version) sortedMap.get(bundleName);
				// if none, we can simply put in what we have
				if (possibleVersion == null) {
					sortedMap.put(bundleName, bundleVersion);
				}
				else {
					int comp = bundleVersion.compareTo(possibleVersion);
					if (comp > 0) {
						// new one is higher, so put it in, else
						// it's fine the way it is
						sortedMap.put(bundleName, bundleVersion);
					}
				}
			}
		}
		return sortedMap;
	}

	private boolean contains(String needle, String[] haystack) {
		boolean result = false;

		for (int i = 0; i < haystack.length; i++) {
			if (needle.equals(haystack[i])) {
				result = true;
				break;
			}
		}
		return result;
	}

	/**
	 * This method is entirely to shorten the (old) long, redundant form of a
	 * build label, such as M-M200612071701-200612071701 to it's equivilant
	 * short form such as M200612071701
	 * 
	 * @param label
	 * @return
	 */
	private String clean(String label) {
		String result = label;

		String possibleResult = null;
		int hPos = label.indexOf('-');
		if (hPos > -1) {
			possibleResult = label.substring(hPos + 1);
			hPos = possibleResult.indexOf('-');
			if (hPos > -1) {
				possibleResult = possibleResult.substring(0, hPos);
				result = possibleResult;
			}
		}


		return result;
	}

	private String cleanWhiteSpace(String text) {
		// trims all chars <= \\\\0020 so should handle CR LF TABs also
		String result = text.trim();
		return result;
	}
}
