Skip to content

Commit

Permalink
harmonize db.get* methods; multithreaded usage search for units
Browse files Browse the repository at this point in the history
  • Loading branch information
msrocka committed Mar 3, 2022
1 parent 19d4a50 commit 1a4ac58
Show file tree
Hide file tree
Showing 19 changed files with 187 additions and 168 deletions.
17 changes: 14 additions & 3 deletions olca-core/src/main/java/org/openlca/core/database/IDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
import org.openlca.core.model.AbstractEntity;
import org.openlca.core.model.ModelType;
import org.openlca.core.model.RefEntity;
import org.openlca.core.model.RootEntity;
import org.openlca.core.model.descriptors.Descriptor;
import org.openlca.core.model.descriptors.RootDescriptor;

/**
* The common interface for openLCA databases.
Expand Down Expand Up @@ -225,7 +227,7 @@ default <T extends RefEntity> Descriptor getDescriptor(
* Get all entities of the given type from this database.
*/
@SuppressWarnings("unchecked")
default <T extends RefEntity> List<T> allOf(Class<T> type) {
default <T extends RefEntity> List<T> getAll(Class<T> type) {
var modelType = ModelType.forModelClass(type);
if (modelType == null)
return Collections.emptyList();
Expand All @@ -238,7 +240,7 @@ default <T extends RefEntity> List<T> allOf(Class<T> type) {
/**
* Get the descriptors of all entities of the given type from this database.
*/
default <T extends RefEntity> List<? extends Descriptor> allDescriptorsOf(
default <T extends RefEntity> List<? extends Descriptor> getDescriptors(
Class<T> type) {
var modelType = ModelType.forModelClass(type);
var dao = Daos.refDao(this, modelType);
Expand All @@ -247,12 +249,21 @@ default <T extends RefEntity> List<? extends Descriptor> allDescriptorsOf(
: dao.getDescriptors();
}

default <T extends RootEntity> List<? extends RootDescriptor> getDescriptors(
Class<T> type, HashSet<Long> ids) {
var modelType = ModelType.forModelClass(type);
var dao = Daos.root(this, modelType);
return dao != null
? dao.getDescriptors(ids)
: Collections.emptyList();
}

/**
* Get the first entity of the given type and with the given name from the
* database. It returns `null` if no entity with the given name exists.
*/
@SuppressWarnings("unchecked")
default <T extends RefEntity> T forName(Class<T> type, String name) {
default <T extends RefEntity> T getForName(Class<T> type, String name) {
var modelType = ModelType.forModelClass(type);
if (modelType == null)
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.List;
import java.util.Set;

import gnu.trove.set.hash.TLongHashSet;
import jakarta.persistence.Table;
import org.openlca.core.model.ModelType;
import org.openlca.core.model.RefEntity;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.openlca.core.database.usage;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

import org.openlca.core.database.IDatabase;
import org.openlca.core.database.NativeSql;
import org.openlca.core.model.Epd;
import org.openlca.core.model.ImpactCategory;
import org.openlca.core.model.Process;
import org.openlca.core.model.Project;
import org.openlca.core.model.Result;
import org.openlca.core.model.RootEntity;
import org.openlca.core.model.SocialIndicator;
import org.openlca.core.model.Unit;
import org.openlca.core.model.descriptors.RootDescriptor;

/**
* Searches for data sets where a unit is used. This does not include the unit
* group where the unit is defined.
*/
public record UnitUsageSearch(IDatabase db, Unit unit) {

public List<RootDescriptor> run() {
if (unit == null || db == null)
return Collections.emptyList();
try {
var exec = Executors.newFixedThreadPool(5);
var results = exec.invokeAll(List.of(
q(Process.class,
"tbl_exchanges", "f_owner", "f_unit"),
q(ImpactCategory.class,
"tbl_impact_factors", "f_impact_category", "f_unit"),
q(Project.class,
"tbl_project_variants", "f_project", "f_unit"),
q(Result.class,
"tbl_flow_results", "f_result", "f_unit"),
q(SocialIndicator.class,
"tbl_social_indicators", "id", "f_activity_unit"),
q(Epd.class,
"tbl_epds", "id", "f_unit")
));
exec.shutdown();
var descriptors = new ArrayList<RootDescriptor>();
for (var result : results) {
descriptors.addAll(result.get());
}
return descriptors;
} catch (Exception e) {
throw new RuntimeException("failed to query for usages of " + unit, e);
}
}

private <T extends RootEntity> Callable<List<? extends RootDescriptor>> q(
Class<T> type, String table, String entityField, String unitField) {
return () -> {
var query = "select distinct " + entityField
+ " from " + table + " where " + unitField + " = " + unit.id;
var ids = new HashSet<Long>();
NativeSql.on(db).query(query, r -> {
ids.add(r.getLong(1));
return true;
});
return ids.isEmpty()
? Collections.emptyList()
: db.getDescriptors(type, ids);
};
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class CategorySync {
private CategorySync(IDatabase db) {
this.db = db;
cache = new EnumMap<>(ModelType.class);
for (var category : db.allOf(Category.class)) {
for (var category : db.getAll(Category.class)) {
if (category.modelType == null)
continue;
var path = category.toPath();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class ExchangeProviderQueue {

private ExchangeProviderQueue(IDatabase db) {
this.db = Objects.requireNonNull(db);
db.allDescriptorsOf(Process.class)
db.getDescriptors(Process.class)
.forEach(d -> processIds.put(d.refId, d.id));
}

Expand Down
4 changes: 2 additions & 2 deletions olca-core/src/test/java/examples/SubResultTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static void main(String[] args) {

// var methodId = "eb4db92d-97ac-41a7-9573-05566a319b06";
// var method = db.get(ImpactMethod.class, methodId);
var results = db.allOf(Result.class)
var results = db.getAll(Result.class)
.stream()
.filter(r -> method.equals(r.impactMethod))
.toList();
Expand Down Expand Up @@ -121,7 +121,7 @@ private static Exchange findExchangeOf(Process process, Flow flow) {


private static Method tagWithMethods(IDatabase db) {
var allResults = db.allOf(Result.class);
var allResults = db.getAll(Result.class);


var methods = new ArrayList<Method>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package org.openlca.core.database.usage;


import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openlca.core.Tests;
import org.openlca.core.database.IDatabase;
import org.openlca.core.model.Exchange;
import org.openlca.core.model.ImpactCategory;
import org.openlca.core.model.ImpactFactor;
import org.openlca.core.model.Process;
import org.openlca.core.model.RootEntity;
import org.openlca.core.model.SocialIndicator;
import org.openlca.core.model.Unit;
import org.openlca.core.model.UnitGroup;
import org.openlca.core.model.descriptors.Descriptor;

public class UnitUsageSearchTest {

private final IDatabase db = Tests.getDb();
private UnitUsageSearch search;
private UnitGroup group;
private Unit unit;

@Before
public void setup() {
group = db.insert(UnitGroup.of("Units of mass", "kg"));
unit = group.referenceUnit;
search = new UnitUsageSearch(db, unit);
}

@After
public void tearDown() {
db.delete(group);
}

@Test
public void testFindNoUsage() {
var models = search.run();
Assert.assertNotNull(models);
Assert.assertTrue(models.isEmpty());
}

@Test
public void testFindInImpactCategories() {
var impact = ImpactCategory.of("my impact");
var factor = new ImpactFactor();
factor.unit = unit;
impact.impactFactors.add(factor);
check(impact);
}

@Test
public void testFindInProcesses() {
var process = new Process();
var exchange = new Exchange();
exchange.unit = unit;
process.exchanges.add(exchange);
check(process);
}

@Test
public void testFindInSocialIndicator() {
var indicator = new SocialIndicator();
indicator.name = "indicator";
indicator.activityUnit = unit;
check(indicator);
}

private void check(RootEntity e) {
db.insert(e);
var results = search.run();
db.delete(e);
var expected = Descriptor.of(e);
Assert.assertEquals(1, results.size());
Assert.assertEquals(expected, results.get(0));
}

}

This file was deleted.

Loading

0 comments on commit 1a4ac58

Please sign in to comment.