/*******************************************************************************
* Copyright © 2011, 2013 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.edt.gen;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public abstract class CommandProcessor {
private List<String> templatePath = new ArrayList<String>();
private List<String> nativeTypePath = new ArrayList<String>();
private List<String> primitiveTypePath = new ArrayList<String>();
private List<String> messagePath = new ArrayList<String>();
private Map<String, CommandParameter> parameterMapping = new HashMap<String, CommandParameter>();
private Map<String, String> aliasMapping = new HashMap<String, String>();
private List<String> supportedPartTypes = new ArrayList<String>();
private List<String> supportedStereotypes = new ArrayList<String>();
public CommandProcessor() {
}
public boolean processBase(String[] args) {
try {
// apply the command line overrides
installOverrides(args, true);
return true;
}
catch (PromptQueryException e) {
System.out.println(e.getMessage());
return false;
}
catch (UnknownParameterException e) {
System.out.println("This parameter is unknown: " + e.getMessage());
return false;
}
catch (MissingParameterValueException e) {
System.out.println("This value for this parameter is missing: " + e.getMessage());
return false;
}
catch (InvalidParameterValueException e) {
System.out.println("This value for this parameter is incorrect: " + e.getMessage());
return false;
}
}
public boolean processUser(String[] args) {
try {
// apply the command line overrides
installOverrides(args, false);
return true;
}
catch (PromptQueryException e) {
System.out.println(e.getMessage());
return false;
}
catch (UnknownParameterException e) {
System.out.println("This parameter is unknown: " + e.getMessage());
return false;
}
catch (MissingParameterValueException e) {
System.out.println("This value for this parameter is missing: " + e.getMessage());
return false;
}
catch (InvalidParameterValueException e) {
System.out.println("This value for this parameter is incorrect: " + e.getMessage());
return false;
}
}
private void installOverrides(String[] args, boolean baseMode) throws PromptQueryException, UnknownParameterException, InvalidParameterValueException,
MissingParameterValueException {
// process only if in base mode
if (baseMode) {
// clean out any previous contributions
templatePath.clear();
nativeTypePath.clear();
primitiveTypePath.clear();
messagePath.clear();
supportedPartTypes.clear();
supportedStereotypes.clear();
// now go through every existing option and clear the value
for (Entry<String, CommandParameter> entry : parameterMapping.entrySet()) {
CommandParameter parameter = entry.getValue();
parameter.setValue(null);
}
}
// process only if in user mode
if (!baseMode) {
// check to see if we have any prompt queries, that provide help for the various parameters. if there are some,
// generate the resulting text and use that as the message for a PromptQueryException. This allows us to prevent
// the generation to proceed
String prompt = "";
for (int i = 0; i < args.length; i++) {
if (args[i].equals("?")) {
// we need to give the prompts for all parameters
for (Entry<String, CommandParameter> entry : parameterMapping.entrySet()) {
CommandParameter parameter = entry.getValue();
// get the prompt value and append
prompt = prompt + parameter.getPromptText() + "\n";
}
} else if (args[i].startsWith("?")) {
// we need to get the prompt for this parameter
String alias = args[i].substring(1);
// we have the alias, so check to make sure it exists
String internalName = getAlias(alias);
if (internalName == null)
throw new UnknownParameterException(alias);
// we now have the internal name, which points at the command parameter, make sure everything is okay
CommandParameter parameter = getParameter(internalName);
if (parameter == null)
throw new UnknownParameterException(internalName);
// get the prompt value and append
prompt = prompt + parameter.getPromptText() + "\n";
}
}
if (prompt.length() > 0)
throw new PromptQueryException(prompt);
}
// override with any command line options
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("-")) {
// split the option using the = sign as the splitter
String alias = args[i].substring(1);
// we have the alias, so check to make sure it exists
String internalName = getAlias(alias);
// if we are processing in base mode, skip unknown arguments
if (internalName == null && baseMode)
continue;
// if we didn't find this alias, then throw an error
if (internalName == null)
throw new UnknownParameterException(alias);
// we now have the internal name, which points at the command parameter, make sure everything is okay
CommandParameter parameter = getParameter(internalName);
if (parameter == null)
throw new UnknownParameterException(internalName);
// make sure the value is acceptible, based on the definitions.
if (parameter.getPossibleValues() instanceof Boolean[]) {
// here we are processing either a Boolean[], which means the argument is part of the -x value, or simply
// -x
boolean valid = false;
Boolean replacementValue = new Boolean(true);
String value = "true";
if (i + 1 < args.length && !args[i + 1].startsWith("-") && !args[i + 1].startsWith("?")) {
value = args[i + 1];
i++;
}
Object[] possibleValues = parameter.getPossibleValues();
for (Object possibleValue : possibleValues) {
if (possibleValue instanceof Boolean) {
if ((Boolean) possibleValue && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"))) {
valid = true;
replacementValue = new Boolean(true);
} else if (!((Boolean) possibleValue) && (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no"))) {
valid = true;
replacementValue = new Boolean(false);
}
}
}
// did we get a match
if (!valid)
throw new InvalidParameterValueException(value);
// replace the value of the command parameter
parameter.setValue(replacementValue);
} else if (parameter.getPossibleValues() instanceof String[]) {
// here we are processing either a String[], which means the argument is part of the -x value, or simply
// -x
boolean valid = false;
String replacementValue = "";
String value = "";
if (i + 1 < args.length && !args[i + 1].startsWith("-") && !args[i + 1].startsWith("?")) {
value = args[i + 1];
i++;
}
Object[] possibleValues = parameter.getPossibleValues();
for (Object possibleValue : possibleValues) {
// null means that any value is allowed
if (possibleValue == null) {
valid = true;
replacementValue = value;
} else if (possibleValue instanceof String) {
if (value.equalsIgnoreCase((String) possibleValue)) {
valid = true;
replacementValue = value;
}
}
}
// did we get a match
if (!valid)
throw new InvalidParameterValueException(value);
// replace the value of the command parameter
parameter.setValue(replacementValue);
} else {
// we are processing an Object[], which means that we want to accept all of the trailing arguments until
// the next -argument, and validate each against the criteria, and append to an Object[] of values
List<String> replacementValue = new ArrayList<String>();
while (i + 1 < args.length) {
if (args[i + 1].startsWith("-"))
break;
// accept this parameter, validate and add to array
boolean valid = false;
Object[] possibleValues = parameter.getPossibleValues();
for (Object possibleValue : possibleValues) {
// null means that any value is allowed
if (possibleValue == null)
valid = true;
else if (possibleValue instanceof String) {
if (args[i + 1].equalsIgnoreCase((String) possibleValue))
valid = true;
}
}
// did we get a match
if (valid)
replacementValue.add(args[i + 1]);
else
throw new InvalidParameterValueException(args[i + 1]);
// increment index
i++;
}
// replace the value of the command parameter
parameter.setValue(replacementValue.toArray());
}
}
}
// process only if in user mode
if (!baseMode) {
// now go through every option and make sure that all required options have been defined by the user
for (Entry<String, CommandParameter> entry : parameterMapping.entrySet()) {
CommandParameter parameter = entry.getValue();
if (parameter.isRequired() && parameter.getValue() == null)
throw new MissingParameterValueException(entry.getKey());
}
}
}
public void installParameter(boolean required, String internalName, String[] aliases, Object[] possibleValues, String promptText) {
// required indicates that this option must have specified a value from the user (or defaulted to the 1st
// possibleValue if not specified as null), and if it hasn't been defined, then an exception will be thrown at the
// end of the install override method
//
// parameters are defined with 3 different possibilities for possibles values, defined by the Object[] type that
// comes in. For the Object[] types, the description is below:
// 1) Boolean[] means that only true or false, yes or no are accepted and the value will be set to a Boolean object
// 2) String[] provides a list of possible string values that can be specified (case insensitive), or null which
// means any value. Exactly 1 String will be returned when querying this parameter, which could be a null value.
// 3) Object[] means that the value(s) that follow the command in the override, will be inserted into a list of 0 or
// more Strings, depending on how many are provided. Each value is checked against the String values provided in the
// list.
//
// For example the command override line is "-abc value1 value2 value3 -path c:\Eclipse" and the parameter is:
// this.installParameter(false, Constants.parameter_list, new String[] { "list" }, new Object[] { null },
// "List of values");
// then the Object[] of 1 null entry means that any string value is accepted and the resulting value on a getValue()
// method call will contain a String[] of "value1", "value2", "value3". The -path operand would not be included as
// the hyphen denotes the next parameter
//
// For example the command override line is "-abc value1 value2 -path c:\Eclipse" and the parameter is:
// this.installParameter(false, Constants.parameter_list, new String[] { "list" }, new Object[] { "value1", "value2"
// }, "List of values");
// then the Object[] of 2 entries means that only those string values that match are accepted and the resulting value
// on a getValue() method call will contain a String[] of "value1", "value2". The -path operand would not be included
// as the hyphen denotes the next parameter
//
// For example the command override line is "-abc value1 value2 value3 -path c:\Eclipse" and the parameter is:
// this.installParameter(false, Constants.parameter_list, new String[] { "list" }, new Object[] { "value1", "value2"
// }, "List of values");
// then an exception will be thrown because the "value3" didn't match any entry in the Object[] definition
// define the internal name key, with the command parameter information
if (getParameter(internalName) != null)
return;
CommandParameter parameter = new CommandParameter(required, possibleValues, possibleValues[0], promptText);
parameterMapping.put(internalName, parameter);
// define each of the aliases to point at the internal name key
if (aliases != null) {
for (String alias : aliases) {
if (alias != null) {
if (getAlias(alias) != null) {
System.out.println("This alias already exists: " + alias + ". It has been ignored.");
return;
}
aliasMapping.put(alias.toLowerCase(), internalName);
}
}
}
}
private String getAlias(String aliasName) {
return this.aliasMapping.get(aliasName.toLowerCase());
}
public CommandParameter getParameter(String internalName) {
return this.parameterMapping.get(internalName);
}
public Map<String, CommandParameter> getParameterMapping() {
return parameterMapping;
}
public List<String> getTemplatePath() {
return templatePath;
}
public List<String> getNativeTypePath() {
return nativeTypePath;
}
public List<String> getPrimitiveTypePath() {
return primitiveTypePath;
}
public List<String> getMessagePath() {
return messagePath;
}
public List<String> getSupportedPartTypes() {
return supportedPartTypes;
}
public List<String> getSupportedStereotypes() {
return supportedStereotypes;
}
}