/**
*
*/
package org.javabuilders;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* Defines a list of items that can be passed to a property
* @author Jacek Furmankiewicz
*
*/
public class ValueListDefinition {
/**
* @param relatedTypes Related classes (used mostly for event handlers)
* @return Common event definitions
*/
public static List<ValueListDefinition> getCommonEventDefinitions(Class<?>...relatedTypes) {
List<ValueListDefinition> eventDefs = new ArrayList<ValueListDefinition>();
//defines the standard event listener definitions
ValueListDefinition vlDef = new ValueListDefinition();
ValueDefinition def = new ValueDefinition("methodName",EventMethod.class);
def.setVariableLength(true);
def.setRelatedTypes(relatedTypes);
vlDef.addValueDefinition(def);
eventDefs.add(vlDef);
return eventDefs;
}
private List<ValueDefinition> valueDefs = new LinkedList<ValueDefinition>();
/**
* Constructor for a list that has unlimited elements of one type
* @param type Value definitions
*/
public ValueListDefinition(ValueDefinition...valueDefs) {
this.valueDefs = new LinkedList<ValueDefinition>(Arrays.asList(valueDefs));
validateValueDefinitions();
}
/**
* @param valueDef Value definition
* @return Same instance, for use in Builder pattern
*/
public ValueListDefinition addValueDefinition(ValueDefinition valueDef) {
valueDefs.add(0,valueDef);
validateValueDefinitions();
return this;
}
//validates if the value defs are valid
private void validateValueDefinitions() {
boolean noMoreAllowed = false;
//only the last value may be of variable length
for(ValueDefinition def : valueDefs) {
if (noMoreAllowed) {
throw new BuildException("Only the last value definition may have variable length");
} else if (def.isVariableLength()) {
noMoreAllowed = true;
}
}
}
/**
* Checks if the values are a potential match
* @param values Values
* @return true/false
*/
public boolean isPotentialMatch(List<Object> values) {
boolean potential = false;
for(@SuppressWarnings("unused")
Object value : values) {
//TODO
}
return potential;
}
/**
* Applies the defaults to a list of values if they are not defined (null/empty) or missing
* @param values Values
*/
public void applyDefaults(List<Object> values) {
int i = 0;
for(ValueDefinition valueDef : valueDefs) {
if (values.size() > i) {
//override a missing value with the default
Object value = values.get(i);
if (value == null || (String.valueOf(value).length() == 0)) {
//apply default
values.set(i, valueDef.getDefaultValue());
}
} else {
//add the default to the list of values
values.add(valueDef.getDefaultValue());
}
i++;
}
}
/**
* @param values
* @return true/false
*/
public boolean isExactMatch(List<Object> values) {
boolean exact = true;
if (valueDefs.size() <= values.size()) {
ValueDefinition variableDef = null;
for(int i = 0; i < values.size(); i++) {
//handle variable length value definitions
Class<?> def = null;
if (variableDef != null) {
def = variableDef.getType();;
} else {
ValueDefinition valueDef = valueDefs.get(i);
def = valueDef.getType();
if (valueDef.isVariableLength()) {
variableDef = valueDef;
}
}
Class<?> value = values.get(i).getClass();
//do the data types match up?
if (def.equals(NamedObject.class)) {
if(!value.equals(String.class)) {
//object names are always strings
exact = false;
break;
}
} else if (def.equals(EventMethod.class)) {
if (!value.equals(String.class)) {
//method names are always Strings
exact = false;
break;
}
} else if (!def.isAssignableFrom(value)){
//data type must be compatible
exact = false;
break;
}
}
} else {
exact = false;
}
return exact;
}
/**
* Validates the values that were passed. Should be called only
* after isExactMatch() was successful
* @param values Values to validate
* @param result Build result
* @param node Node
* @param valueList Value list being built
* @throws BuildException Thrown if any exception occurs
*/
@SuppressWarnings("unchecked")
public Values validateValues(List<Object> values, BuildProcess result, Node node,
Values valueList) throws BuildException {
Values validations = new Values(this);
ValueDefinition variableDef = null;
for(int i = 0; i < values.size();i++) {
ValueDefinition def = null;
if (variableDef != null) {
def = variableDef;
} else {
def = valueDefs.get(i);
if (def.isVariableLength()) {
variableDef = def;
}
}
Object value = values.get(i);
def.validateValue(result, node, value, valueList);
}
return validations;
}
}