package eu.esdihumboldt.hale.common.service.helper.population;
import java.util.ArrayList;
import java.util.List;
import eu.esdihumboldt.hale.common.align.model.AlignmentUtil;
import eu.esdihumboldt.hale.common.align.model.ChildContext;
import eu.esdihumboldt.hale.common.align.model.EntityDefinition;
import eu.esdihumboldt.hale.common.instance.model.Group;
import eu.esdihumboldt.hale.common.instance.model.Instance;
/**
* Helper class for Population Service
*
* @author Arun
*/
public class EntityPopulationCount {
private final IPopulationUpdater notifier;
/**
* Constructor
*
* @param notifier {@link IPopulationUpdater}
*/
public EntityPopulationCount(IPopulationUpdater notifier) {
this.notifier = notifier;
}
/**
* Count the population for the properties of the given group.
*
* @param group the group
* @param groupDef the group entity definition
*/
public void addToPopulation(Group group, EntityDefinition groupDef) {
Iterable<? extends EntityDefinition> children = this.notifier.getChildren(groupDef);
if (children != null && children.iterator().hasNext()) {
for (EntityDefinition def : children) {
evaluateContext(group, def);
}
}
else {
evaluateContext(group, groupDef);
}
}
/**
* Count population of {@link EntityDefinition}
*
* @param entityDef a entity definition
* @param instance an instance
*/
public void countPopulation(EntityDefinition entityDef, Instance instance) {
List<ChildContext> path = entityDef.getPropertyPath();
if (path == null || path.isEmpty()) {
if (entityDef.getFilter() == null || entityDef.getFilter().match(instance)) {
increase(entityDef, 1);
addToPopulation(instance, entityDef);
}
}
else {
evaluateChildEntityDefinition(instance, entityDef, path);
}
}
/**
* count the population for the given entity with all contexts
*
* @param group A {@link Group}
* @param groupDef An {@link EntityDefinition}
*/
private void evaluateContext(Group group, EntityDefinition groupDef) {
List<ChildContext> path = groupDef.getPropertyPath();
if (path != null && !path.isEmpty()) {
ChildContext context = path.get(path.size() - 1);
Object[] values = group.getProperty(context.getChild().getName());
if (values != null) {
// apply the possible source contexts
if (context.getIndex() != null) {
// select only the item at the index
int index = context.getIndex();
if (index < values.length) {
values = new Object[] { values[index] };
}
else {
values = new Object[] {};
}
}
if (context.getCondition() != null) {
// select only values that match the condition
List<Object> matchedValues = new ArrayList<Object>();
for (Object value : values) {
if (AlignmentUtil.matchCondition(context.getCondition(), value, group)) {
matchedValues.add(value);
}
}
values = matchedValues.toArray();
}
if (context.getChild().getName().equals(groupDef.getDefinition().getName())) {
increase(groupDef, values.length);
}
for (Object value : values) {
if (value instanceof Group) {
addToPopulation((Group) value, groupDef);
}
}
}
else {
increase(groupDef, 0);
}
}
}
private void evaluateChildEntityDefinition(Group group, EntityDefinition groupDef,
List<ChildContext> path) {
if (path.size() == 1) {
evaluateContext(group, groupDef);
}
else {
ChildContext context = path.get(0);
List<ChildContext> subPath = path.subList(1, path.size());
Object[] values = group.getProperty(context.getChild().getName());
if (values != null) {
for (Object value : values) {
if (value instanceof Group) {
evaluateChildEntityDefinition((Group) value, groupDef, subPath);
}
}
}
else {
evaluateChildEntityDefinition(group, groupDef, subPath);
}
}
}
private void increase(EntityDefinition def, int count) {
notifier.increaseForEntity(def, count);
}
}