package org.openlca.core.database; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import org.openlca.core.model.Category; import org.openlca.core.model.ModelType; import org.openlca.core.model.descriptors.CategoryDescriptor; public class CategoryDao extends CategorizedEntityDao<Category, CategoryDescriptor> { public CategoryDao(IDatabase database) { super(Category.class, CategoryDescriptor.class, database); } @Override protected String[] getDescriptorFields() { return new String[] { "id", "ref_id", "name", "description", "version", "last_change", "f_category", "model_type" }; } @Override protected CategoryDescriptor createDescriptor(Object[] queryResult) { CategoryDescriptor descriptor = super.createDescriptor(queryResult); if (queryResult[7] instanceof String) descriptor.setCategoryType(ModelType .valueOf((String) queryResult[7])); return descriptor; } /** Root categories do not have a parent category. */ public List<Category> getRootCategories(ModelType type) { String jpql = "select c from Category c where c.category is null " + "and c.modelType = :type"; return getAll(jpql, Collections.singletonMap("type", type)); } /** Root categories do not have a parent category. */ public List<Category> getRootCategories() { String jpql = "select c from Category c where c.category is null"; Map<String, Object> m = Collections.emptyMap(); return getAll(jpql, m); } @Override // see update(category) public Category insert(Category category) { category.setRefId(Category.createRefId(category)); Category existing = getForRefId(category.getRefId()); if (existing != null) { mergeChildren(existing, category); return update(existing); } return super.insert(category); } @Override // categories should be identified by their path, therefore the refID will // be generated depending on the category path. This way, we can treat the // category model as a normal entity and still compare categories by path public Category update(Category category) { String refId = category.getRefId(); String newRefId = Category.createRefId(category); Category forRefId = getForRefId(newRefId); if (Objects.equals(refId, newRefId) || forRefId == null) { category.setRefId(newRefId); category = super.update(category); for (Category child : category.getChildCategories()) update(child); return category; } mergeChildren(forRefId, category); forRefId = super.update(forRefId); for (Category child : forRefId.getChildCategories()) update(child); return forRefId; } private void mergeChildren(Category into, Category from) { for (Category child : from.getChildCategories()) { if (contains(into.getChildCategories(), child)) continue; child.setCategory(into); into.getChildCategories().add(child); } } private boolean contains(List<Category> categories, Category category) { for (Category child : categories) if (Category.createRefId(child).equals(Category.createRefId(category))) return true; return false; } }