/**
 * 
 */
package org.openforis.idm.metamodel;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.openforis.idm.model.IntegerRange;
import org.openforis.idm.model.IntegerRangeAttribute;
import org.openforis.idm.model.Node;
import org.openforis.idm.model.NumericRange;
import org.openforis.idm.model.RealRange;
import org.openforis.idm.model.RealRangeAttribute;
import org.openforis.idm.model.Value;

/**
 * @author G. Miceli
 * @author M. Togna
 */
public class RangeAttributeDefinition extends NumericAttributeDefinition {

	private static final long serialVersionUID = 1L;
	
	public static final String FROM_FIELD = "from";
	public static final String TO_FIELD = "to";

	private final FieldDefinition<Integer> integerFromField = new FieldDefinition<Integer>(FROM_FIELD, "f", FROM_FIELD, Integer.class, this);
	private final FieldDefinition<Integer> integerToField = new FieldDefinition<Integer>(TO_FIELD, "t", TO_FIELD, Integer.class, this);
	private final FieldDefinition<Double> realFromField = new FieldDefinition<Double>(FROM_FIELD, "f", FROM_FIELD, Double.class, this);
	private final FieldDefinition<Double> realToField = new FieldDefinition<Double>(TO_FIELD, "t", TO_FIELD, Double.class, this);
	private final FieldDefinition<String> unitNameField = new FieldDefinition<String>(UNIT_NAME_FIELD, "u_name", "unit", String.class, this);;
	private final FieldDefinition<Integer> unitIdField = new FieldDefinition<Integer>(UNIT_FIELD, "u", "unit_id", Integer.class, this);;
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private final List integerTypeFieldDefinitions = Collections.unmodifiableList(Arrays.asList(integerFromField, integerToField, unitNameField, unitIdField));
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private final List realTypeFieldDefinitions = Collections.unmodifiableList(Arrays.asList(realFromField, realToField, unitNameField, unitIdField));
	
	RangeAttributeDefinition(Survey survey, int id) {
		super(survey, id);
	}

	@Override
	public Node<?> createNode() {
		Type effectiveType = getType();
		switch (effectiveType) {
		case INTEGER:
			return new IntegerRangeAttribute(this);
		case REAL:
			return new RealRangeAttribute(this);
		default:
			throw new UnsupportedOperationException("Unknown type");
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public NumericRange<? extends Number> createValue(String string) {
		if ( StringUtils.isBlank(string) ) {
			return null;
		} 
		Unit unit = getDefaultUnit();
		if (isInteger()) {
			return IntegerRange.parseIntegerRange(string, unit);
		} else if (isReal()) {
			return RealRange.parseRealRange(string, unit);
		}
		throw new RuntimeException("Invalid range type " + getType());
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<FieldDefinition<?>> getFieldDefinitions() {
		switch (getType()) {
		case INTEGER:
			return integerTypeFieldDefinitions;
		case REAL:
			return realTypeFieldDefinitions;
		default:
			throw new UnsupportedOperationException("Unknown type");
		}
	}
	
	@Override
	public FieldDefinition<?> getFieldDefinition(String name) {
		for (FieldDefinition<?> def : getFieldDefinitions()) {
			if(def.getName().equals(name)) {
				return def;
			}
		}
		return null;
	}
	
	@Override
	public Class<? extends Value> getValueType() {
		Type type = getType();
		switch (type) {
		case INTEGER:
			return IntegerRange.class;
		case REAL:
			return RealRange.class;
		default:
			throw new UnsupportedOperationException("Unknown type");
		}
	}
	
	@Override
	public String getMainFieldName() {
		throw new IllegalArgumentException("Main field not defined");
	}
	
	@Override
	protected FieldDefinitionMap getFieldDefinitionMap() {
		throw new UnsupportedOperationException();
	}
	
}

@@ -47,87 +47,8 @@
 l;%0A%0A
-import java.util.Arrays;%0Aimport java.util.Collections;%0Aimport java.util.List;%0A%0A
 impo
@@ -88,16 +88,16 @@
 gUtils;%0A
+
 import o
@@ -1486,82 +1486,48 @@
 %0A%09%0A%09
-@SuppressWarnings(%7B %22rawtypes%22, %22unchecked%22 %7D)%0A%09private final List
+private final FieldDefinitionMap
  integer
 Type
@@ -1514,36 +1514,32 @@
 itionMap integer
-Type
 FieldDefinitions
@@ -1541,54 +1541,39 @@
 tion
-s = Collections.unmodifiableList(Arrays.asList
+ByName = new FieldDefinitionMap
 (int
@@ -1634,87 +1634,48 @@
 eld)
-)
 ;%0A%09
-@SuppressWarnings(%7B %22rawtypes%22, %22unchecked%22 %7D)%0A%09private final List
+private final FieldDefinitionMap
  real
-Type
 Fiel
@@ -1689,54 +1689,39 @@
 tion
-s = Collections.unmodifiableList(Arrays.asList
+ByName = new FieldDefinitionMap
 (rea
@@ -1772,17 +1772,16 @@
 IdField)
-)
 ;%0A%09%0A%09Ran
@@ -2579,315 +2579,8 @@
 %7D%0A%09%0A
-%09@SuppressWarnings(%22unchecked%22)%0A%09@Override%0A%09public List%3CFieldDefinition%3C?%3E%3E getFieldDefinitions() %7B%0A%09%09switch (getType()) %7B%0A%09%09case INTEGER:%0A%09%09%09return integerTypeFieldDefinitions;%0A%09%09case REAL:%0A%09%09%09return realTypeFieldDefinitions;%0A%09%09default:%0A%09%09%09throw new UnsupportedOperationException(%22Unknown type%22);%0A%09%09%7D%0A%09%7D%0A%09%0A
 %09@Ov
@@ -3232,24 +3232,165 @@
 tionMap() %7B%0A
+%09%09switch (getType()) %7B%0A%09%09case INTEGER:%0A%09%09%09return integerFieldDefinitionByName;%0A%09%09case REAL:%0A%09%09%09return realFieldDefinitionByName;%0A%09%09default:%0A%09
 %09%09throw new 
@@ -3419,18 +3419,36 @@
 ception(
-);
+%22Unknown type%22);%0A%09%09%7D
 %0A%09%7D%0A%09%0A%7D%0A

Use field definition map in RangeAttributeDefinition