All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.javabuilders.ValueListDefinition Maven / Gradle / Ivy

The newest version!
/**
 * 
 */
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 getCommonEventDefinitions(Class...relatedTypes) {
		List eventDefs = new ArrayList();
		
		//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 valueDefs = new LinkedList();
	
	/**
	 * Constructor for a list that has unlimited elements of one type
	 * @param type Value definitions
	 */
	public ValueListDefinition(ValueDefinition...valueDefs) {
	
		this.valueDefs = new LinkedList(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 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 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 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 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;
	}

}