/*
* Copyright (c) 2011 Patrick Meyer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.itemanalysis.jmetrik.commandbuilder;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.Iterator;
public class FreeOptionList extends AbstractOption{
private OptionValueType type = OptionValueType.STRING;
private ArrayList<String> stringList = null;
private ArrayList<Double> doubleList = null;
private ArrayList<Integer> intList = null;
public FreeOptionList(String name, OptionValueType type){
this(name, "", false, type);
}
public FreeOptionList(String optionName, String optionDescription, OptionValueType type){
this(optionName, optionDescription, false, type);
}
public FreeOptionList(String optionName, String optionDescription, boolean required, OptionValueType type){
this.optionName = optionName;
this.optionDescription = optionDescription;
this.required = required;
this.type = type;
this.optionType = OptionType.FREE_LIST_OPTION;
if(type== OptionValueType.DOUBLE){
doubleList = new ArrayList<Double>();
}else if(type == OptionValueType.INTEGER){
intList = new ArrayList<Integer>();
}else{
stringList = new ArrayList<String>();
}
}
public boolean hasValue(){
switch(type){
case STRING: return stringList.size()>0;
case INTEGER: return intList.size()>0;
case DOUBLE: return doubleList.size()>0;
}
return false;
}
public int getNumberOfValues(){
switch(type){
case STRING: return stringList.size();
case INTEGER: return intList.size();
case DOUBLE: return doubleList.size();
}
return -1;
}
/**
* Add values to this option in the form of a single value or a comma delimited list of values.
* The values must all be of the same type as indicated by type variable.
*
* This method is used for processing user supplied input.
*
* @param text
*/
public void addValue(String text)throws IllegalArgumentException{
String temp = text.replaceAll("[\\n\\r]", "");//eliminate carriage returns and line feeds
// String[] v = temp.trim().split(",");
String REGEX = ",(?![^()]*+\\))";//split only on commas not contained in parentheses
String[] v = temp.split(REGEX);
try{
if(type== OptionValueType.DOUBLE){
for(int i=0;i<v.length;i++){
doubleList.add(Double.parseDouble(v[i].trim()));
}
}else if(type== OptionValueType.INTEGER){
for(int i=0;i<v.length;i++){
intList.add(Integer.parseInt(v[i].trim()));
}
}else{
for(int i=0;i<v.length;i++){
stringList.add(v[i].replaceAll("\"", "").trim()); //replaceAll eliminates quotes
}
}
}catch(ClassCastException ex){
throw new IllegalArgumentException("Data type mismatch for " + optionName);
}
}
public void addValue(Double value)throws IllegalArgumentException{
if(type!= OptionValueType.DOUBLE) throw new IllegalArgumentException("Double values not allowed in " + optionName + ".");
doubleList.add(value);
}
public void addValue(Integer value)throws IllegalArgumentException{
if(type!= OptionValueType.INTEGER) throw new IllegalArgumentException("Integer values not allowed in " + optionName + ".");
intList.add(value);
}
public ArrayList<String> getString()throws IllegalArgumentException{
if(type!= OptionValueType.STRING) throw new IllegalArgumentException("List does not contain String values " + optionName + ".");
return stringList;
}
public String getStringAt(int index)throws IllegalArgumentException{
if(type!= OptionValueType.STRING) throw new IllegalArgumentException("List does not contain String values " + optionName + ".");
return stringList.get(index);
}
public void removeStringAt(int index)throws IllegalArgumentException{
if(type!= OptionValueType.STRING) throw new IllegalArgumentException("List does not contain String values " + optionName + ".");
stringList.remove(index);
}
public ArrayList<Double> getDouble()throws IllegalArgumentException{
if(type!= OptionValueType.DOUBLE) throw new IllegalArgumentException("List does not contain Double values " + optionName + ".");
return doubleList;
}
public Double getDoubleAt(int index)throws IllegalArgumentException{
if(type!= OptionValueType.DOUBLE) throw new IllegalArgumentException("List does not contain Double values " + optionName + ".");
return doubleList.get(index);
}
public void removeDoubleAt(int index)throws IllegalArgumentException{
if(type!= OptionValueType.DOUBLE) throw new IllegalArgumentException("List does not contain Double values " + optionName + ".");
doubleList.remove(index);
}
public ArrayList<Integer> getInteger()throws IllegalArgumentException{
if(type!= OptionValueType.INTEGER) throw new IllegalArgumentException("List does not contain Integer values " + optionName + ".");
return intList;
}
public Integer getIntegerAt(int index)throws IllegalArgumentException{
if(type!= OptionValueType.INTEGER) throw new IllegalArgumentException("List does not contain Integer values " + optionName + ".");
return intList.get(index);
}
public void removeIntegerAt(int index)throws IllegalArgumentException{
if(type!= OptionValueType.INTEGER) throw new IllegalArgumentException("List does not contain Integer values " + optionName + ".");
intList.remove(index);
}
public void clear(){
switch(type){
case DOUBLE: doubleList.clear(); break;
case INTEGER: intList.clear(); break;
case STRING: stringList.clear(); break;
}
}
public Iterator<String> getStringValueIterator(){
return stringList.iterator();
}
public Iterator<Integer> getIntegerValueIterator(){
return intList.iterator();
}
public Iterator<Double> getDoubleValueIterator(){
return doubleList.iterator();
}
public String paste(){
String list = optionName + "(";
if(type== OptionValueType.DOUBLE){
for(Double d : doubleList){
list += d.toString() + ", ";
}
}else if(type== OptionValueType.INTEGER){
for(Integer i : intList){
list += i.toString() + ", ";
}
}else{
for(String s : stringList){
list += s + ", ";
}
}
list = list.substring(0, list.lastIndexOf(",")).trim(); //eliminate trailing comma and white space
list += ");";
return list;
}
/**
* Processes user input of the form:
*
* option(arg1, arg2, arg3); when there are multiple values
* option(arg1); when there is a single value
*
* All of the values must be of the same type such as all string or all double.
*
* @param line
* @return
* @throws IllegalArgumentException
*/
public void split(String line)throws IllegalArgumentException{
String text = line.replaceAll("[\\n\\r]", "");//eliminate carriage returns and line feeds
text = text.trim();
int first = text.indexOf("(");
int last = text.lastIndexOf(")");
if(first==-1 || last==-1) throw new IllegalArgumentException("Missing opening or closing parentheses for " + optionName);
String opName = text.substring(0, first);
String opValue = text.substring(first+1, last);
try{
if(opName.equals(optionName)){
this.addValue(opValue);
}
}catch(IllegalArgumentException ex){
throw new IllegalArgumentException(ex);
}
}
public String getHelpText(){
Formatter f = new Formatter();
String n = "<" + optionName + ">";
f.format("%5s", ""); f.format("%-20s", "Argument: "); f.format("%-100s", n + " " + optionDescription); f.format("%n");
f.format("%5s", ""); f.format("%-20s", "Values: "); f.format("%-100s", "[LIST: " + type + "]");f.format("%n");
f.format("%5s", ""); f.format("%-20s", "Required: ");
if(required){
f.format("%-3s", "Yes");
}else{
f.format("%-2s", "No");
}
f.format("%5s", "");
f.format("%n");
return f.toString();
}
@Override
public String toString(){
return optionName;
}
@Override
public boolean equals(Object o){
if(!(o instanceof Option)) return false;
if(o==this) return true;
Option arg = (Option)o;
if(arg.toString().equals(this.toString())) return true;
return false;
}
@Override
public int hashCode(){
return optionName.hashCode();
}
}