package de.tudresden.inf.lat.tabula.extension;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

/**
 * This models an extension that can execute other extensions.
 *
 */
public class ExtensionManager implements Extension {

	public static final String NAME = "ext";
	public static final String HELP = "extension manager";
	public static final int REQUIRED_ARGUMENTS = 1;
	public static final char NEW_LINE = '\n';
	public static final char SPACE = ' ';

	private final List<Extension> extensions = new ArrayList<>();
	private final Map<String, Extension> extensionMap = new TreeMap<>();

	/**
	 * Constructs an extension manager.
	 * 
	 * @param extensions
	 *            list of extensions
	 */
	public ExtensionManager(List<Extension> extensions) {
		if (Objects.nonNull(extensions)) {
			this.extensions.addAll(extensions);
			extensions.forEach(extension -> {
				String key = extension.getExtensionName();
				if (this.extensionMap.containsKey(key)) {
					throw new ExtensionException("Only one implementation is allowed for each extension, and '" + key
							+ "' was at least twice.");
				}
				this.extensionMap.put(key, extension);
			});
		}
	}

	@Override
	public boolean process(List<String> arguments) {
		if (Objects.isNull(arguments) || arguments.size() < REQUIRED_ARGUMENTS) {
			return false;
		} else {
			String command = arguments.get(0);
			List<String> newArguments = new ArrayList<>();
			newArguments.addAll(arguments);
			newArguments.remove(0);
			Extension extension = this.extensionMap.get(command);
			if (Objects.isNull(extension)) {
				throw new ExtensionException("Extension '" + command + "' was not found.");
			} else {
				extension.process(newArguments);
				return true;
			}
		}
	}

	@Override
	public String getExtensionName() {
		return NAME;
	}

	@Override
	public String getHelp() {
		StringBuffer sbuf = new StringBuffer();
		this.extensions.forEach(extension -> {
			sbuf.append(extension.getExtensionName());
			sbuf.append(SPACE);
			sbuf.append(extension.getHelp());
			sbuf.append(NEW_LINE);
		});
		return sbuf.toString();
	}

	@Override
	public int getRequiredArguments() {
		return REQUIRED_ARGUMENTS;
	}

}

@@ -41,16 +41,53 @@
 nsion;%0A%0A
+import java.io.UncheckedIOException;%0A
 import j
@@ -204,16 +204,77 @@
 eeMap;%0A%0A
+import de.tudresden.inf.lat.tabula.datatype.ParseException;%0A%0A
 /**%0A * T
@@ -1391,28 +1391,24 @@
 ts) %7B%0A%09%09
-if (
 Objects.
 isNull(a
@@ -1395,26 +1395,34 @@
 %7B%0A%09%09Objects.
-is
+requireNon
 Null(argumen
@@ -1428,12 +1428,16 @@
 nts)
- %7C%7C 
+;%0A%09%09if (
 argu
@@ -1480,20 +1480,68 @@
 %0A%09%09%09
-return false
+throw new ExtensionException(%22No extension name was given.%22)
 ;%0A%09%09
@@ -1886,63 +1886,339 @@
 lse 
-%7B%0A%09%09%09%09extension.process(newArguments);%0A%09%09%09%09return true;
+if (newArguments.size() %3C extension.getRequiredArguments()) %7B%0A%09%09%09%09throw new ExtensionException(%22Insufficient number of arguments for extension '%22 + command + %22'.%22);%0A%09%09%09%7D else %7B%0A%09%09%09%09try %7B%0A%09%09%09%09%09return extension.process(newArguments);%0A%09%09%09%09%7D catch (ParseException %7C UncheckedIOException e) %7B%0A%09%09%09%09%09throw new ExtensionException(e);%0A%09%09%09%09%7D
 %0A%09%09%09

Improve exception handling in extension manager