package org.molgenis.data.mapper.algorithmgenerator.generator;
import com.google.common.collect.Lists;
import org.molgenis.data.DataService;
import org.molgenis.data.mapper.algorithmgenerator.bean.Category;
import org.molgenis.data.mapper.algorithmgenerator.categorymapper.CategoryMapper;
import org.molgenis.data.mapper.algorithmgenerator.categorymapper.FrequencyCategoryMapper;
import org.molgenis.data.mapper.algorithmgenerator.categorymapper.LexicalCategoryMapper;
import org.molgenis.data.mapper.algorithmgenerator.rules.CategoryRule;
import org.molgenis.data.mapper.algorithmgenerator.rules.impl.MissingCategoryRule;
import org.molgenis.data.mapper.algorithmgenerator.rules.impl.NegativeCategoryRule;
import org.molgenis.data.mapper.algorithmgenerator.rules.impl.PositiveCategoryRule;
import org.molgenis.data.meta.model.Attribute;
import org.molgenis.data.meta.model.EntityType;
import java.util.List;
public class OneToOneCategoryAlgorithmGenerator extends AbstractCategoryAlgorithmGenerator
{
private final FrequencyCategoryMapper frequencyCategoryMapper;
private final LexicalCategoryMapper lexicalCategoryMapper;
public OneToOneCategoryAlgorithmGenerator(DataService dataService)
{
super(dataService);
List<CategoryRule> rules = getRules(dataService);
this.lexicalCategoryMapper = new LexicalCategoryMapper(rules);
this.frequencyCategoryMapper = new FrequencyCategoryMapper(rules);
}
private List<CategoryRule> getRules(DataService dataService)
{
return Lists.newArrayList(new NegativeCategoryRule(), new PositiveCategoryRule(), new MissingCategoryRule());
}
@Override
public boolean isSuitable(Attribute targetAttribute, List<Attribute> sourceAttributes)
{
return isXrefOrCategorialDataType(targetAttribute) && (sourceAttributes.stream()
.allMatch(this::isXrefOrCategorialDataType)) && sourceAttributes.size() == 1;
}
@Override
public String generate(Attribute targetAttribute, List<Attribute> sourceAttributes, EntityType targetEntityType,
EntityType sourceEntityType)
{
String mapAlgorithm = null;
if (sourceAttributes.size() > 0)
{
Attribute firstSourceAttribute = sourceAttributes.get(0);
List<Category> targetCategories = convertToCategory(targetAttribute);
List<Category> sourceCategories = convertToCategory(firstSourceAttribute);
// Check if both of target and source categories contain frequency units
if (isFrequencyCategory(targetCategories) && isFrequencyCategory(sourceCategories))
{
mapAlgorithm = mapCategories(firstSourceAttribute, targetCategories, sourceCategories,
frequencyCategoryMapper);
}
else
{
mapAlgorithm = mapCategories(firstSourceAttribute, targetCategories, sourceCategories,
lexicalCategoryMapper);
}
}
return mapAlgorithm;
}
public String mapCategories(Attribute sourceAttribute, List<Category> targetCategories,
List<Category> sourceCategories, CategoryMapper categoryMapper)
{
StringBuilder stringBuilder = new StringBuilder();
for (Category sourceCategory : sourceCategories)
{
Category bestTargetCategory = categoryMapper.findBestCategoryMatch(sourceCategory, targetCategories);
if (bestTargetCategory != null)
{
if (stringBuilder.length() == 0)
{
stringBuilder.append("$('").append(sourceAttribute.getName()).append("')").append(".map({");
}
stringBuilder.append("\"").append(sourceCategory.getCode()).append("\":\"")
.append(bestTargetCategory.getCode()).append("\",");
}
}
if (stringBuilder.length() > 0)
{
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
stringBuilder.append("}, null, null).value();");
}
return stringBuilder.toString();
}
boolean isFrequencyCategory(List<Category> categories)
{
return categories.stream().anyMatch(category -> category.getAmountWrapper() != null);
}
}