package org.openforis.collect.io.data.csv;

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

import org.openforis.idm.metamodel.AttributeDefinition;
import org.openforis.idm.model.Attribute;
import org.openforis.idm.model.Entity;
import org.openforis.idm.model.Field;
import org.openforis.idm.model.Node;

/**
 * @author G. Miceli
 * @author M. Togna
 */
public class SingleFieldAttributeColumnProvider extends BasicAttributeColumnProvider<AttributeDefinition> {
	
	private String headerName;

	public SingleFieldAttributeColumnProvider(CSVExportConfiguration config, AttributeDefinition defn) {
		this(config, defn, defn.getName());
	}
	
	public SingleFieldAttributeColumnProvider(CSVExportConfiguration config, AttributeDefinition defn, String headerName) {
		super(config, defn);
		this.headerName = headerName;
	}
	
	@Override
	protected int getNumberOfColumnsPerAttribute() {
		return 1;
	}
	
	@Override
	protected List<String> generateSingleAttributeColumnHeadings() {
		return Collections.unmodifiableList(Arrays.asList(headerName));
	}
	
	@Override
	protected List<String> generateAttributeColumnHeadings(int i) {
		return Arrays.asList(headerName + "[" + (i + 1) + "]");
	}

	public List<String> extractValues(Node<?> axis) {
		if ( axis == null ) {
			throw new NullPointerException("Axis must be non-null");
		} else if ( axis instanceof Entity ) {
			Entity entity = (Entity) axis;
			int maxAttrValues = getMaxAttributeValues();
			List<String> values = new ArrayList<String>(maxAttrValues);
			int attrCount = entity.getCount(attributeDefinition);
			for (int attrIdx = 0; attrIdx < maxAttrValues; attrIdx++) {
				String val;
				if (attrIdx < attrCount) {
					Attribute<?, ?> attr = (Attribute<?, ?>) entity.getChild(attributeDefinition, attrIdx);
					val = extractValue(attr);
				} else {
					val = "";
				}
				values.add(val);
			}
			return values;
		} else {
			throw new UnsupportedOperationException("Axis must be an Entity");
		}
	}

	private String extractValue(Attribute<?, ?> attr) {
		String mainFieldName = attr.getDefinition().getMainFieldName();
		Field<?> fld = attr.getField(mainFieldName);
		Object v = fld.getValue();
		String stringVal = v == null ? "" : v.toString();
		return stringVal;
	}

}

@@ -200,16 +200,69 @@
 nition;%0A
+import org.openforis.idm.metamodel.EntityDefinition;%0A
 import o
@@ -295,16 +295,16 @@
 ribute;%0A
-
 import o
@@ -1609,16 +1609,73 @@
 alues);%0A
+%09%09%09Entity nearestParentEntity = getParentEntity(entity);%0A
 %09%09%09int a
@@ -1685,17 +1685,30 @@
 Count = 
-e
+nearestParentE
 ntity.ge
@@ -1892,17 +1892,30 @@
 %3C?, ?%3E) 
-e
+nearestParentE
 ntity.ge
@@ -2146,16 +2146,16 @@
 %22);%0A
-
 %09%09%7D%0A%09%7D%0A%0A
 %09pri
@@ -2150,16 +2150,913 @@
 %09%09%7D%0A%09%7D%0A%0A
+%09/**%0A%09 * Attribute definition can be inside nested single entities inside the axis.%0A%09 * This method will look for the nearest parent entity for attributes to extract value for.%0A%09 */%0A%09private Entity getParentEntity(Entity axis) %7B%0A%09%09EntityDefinition entityDef = axis.getDefinition();%0A%09%09List%3CEntityDefinition%3E ancestorEntityDefinitions = attributeDefinition.getAncestorEntityDefinitions();%0A%09%09int indexOfAxis = ancestorEntityDefinitions.indexOf(entityDef);%0A%09%09Entity nearestParentEntity = axis;%0A%09%09if (indexOfAxis + 1 %3C ancestorEntityDefinitions.size()) %7B%0A%09%09%09List%3CEntityDefinition%3E relativeSingleEntityDefs = ancestorEntityDefinitions.subList(indexOfAxis + 1, ancestorEntityDefinitions.size());%0A%09%09%09for (EntityDefinition parentSingleEntityDef : relativeSingleEntityDefs) %7B%0A%09%09%09%09nearestParentEntity = (Entity) nearestParentEntity.getChild(parentSingleEntityDef);%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return nearestParentEntity;%0A%09%7D%0A%0A
 %09private

Fix issue with CSV export not including attributes inside nested single entities