package org.openlca.io.ecospold1.input;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.openlca.core.database.BaseEntityDao;
import org.openlca.core.database.CategoryDao;
import org.openlca.core.database.IDatabase;
import org.openlca.core.model.AbstractEntity;
import org.openlca.core.model.Actor;
import org.openlca.core.model.Category;
import org.openlca.core.model.Flow;
import org.openlca.core.model.Location;
import org.openlca.core.model.ModelType;
import org.openlca.core.model.RootEntity;
import org.openlca.core.model.Source;
import org.openlca.ecospold.IExchange;
import org.openlca.ecospold.IPerson;
import org.openlca.ecospold.ISource;
import org.openlca.ecospold.io.DataSet;
import org.openlca.io.Categories;
import org.openlca.io.UnitMappingEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A wrapper for the database access and (semantic) search of entities for the
* import of EcoSpold data sets.
*/
class DB {
private IDatabase database;
private DBSearch search;
private Logger log = LoggerFactory.getLogger(getClass());
private Map<String, Category> categories = new HashMap<>();
private Map<String, Actor> actors = new HashMap<>();
private Map<String, Source> sources = new HashMap<>();
private Map<String, Location> locations = new HashMap<>();
private Map<String, Flow> flows = new HashMap<>();
public DB(IDatabase database) {
this.database = database;
this.search = new DBSearch(database);
}
public Category getPutCategory(ModelType type, String parentName,
String name) {
String key = StringUtils.join(new Object[] { type.name(), parentName,
name }, "/");
Category category = categories.get(key);
if (category != null)
return category;
try {
CategoryDao dao = new CategoryDao(database);
dao.getRootCategories(type);
Category parent = null;
if (parentName != null) {
parent = Categories.findRoot(database, type, parentName);
if (parent == null)
parent = Categories.createRoot(database, type, parentName);
}
category = parent;
if (name != null) {
if (parent != null)
category = Categories
.findOrAddChild(database, parent, name);
else
category = Categories.createRoot(database, type, name);
}
categories.put(key, category);
return category;
} catch (Exception e) {
log.error("Failed to get category " + key, e);
return null;
}
}
public Category getPutCategory(Category root, String parentName, String name) {
String key = StringUtils.join(new Object[] { root.getName(),
parentName, name }, "/");
Category category = categories.get(key);
if (category != null)
return category;
try {
Category parent = root;
if (parentName != null)
parent = Categories.findOrAddChild(database, root, parentName);
Category cat = parent;
if (name != null)
cat = Categories.findOrAddChild(database, parent, name);
return cacheReturn(key, cat);
} catch (Exception e) {
log.error("Failed to find or add category", e);
return null;
}
}
private Category cacheReturn(String key, Category category) {
categories.put(key, category);
return category;
}
public Actor findActor(IPerson person, String genKey) {
Actor actor = get(Actor.class, actors, genKey);
if (actor != null)
return actor;
actor = search.findActor(person);
if (actor != null)
actors.put(genKey, actor);
return actor;
}
public Source findSource(ISource eSource, String genKey) {
Source source = get(Source.class, sources, genKey);
if (source != null)
return source;
source = search.findSource(eSource);
if (source != null)
sources.put(genKey, source);
return source;
}
public Location findLocation(String locationCode, String genKey) {
Location location = get(Location.class, locations, genKey);
if (location != null)
return location;
location = search.findLocation(locationCode);
if (location != null)
locations.put(genKey, location);
return location;
}
public Flow findFlow(IExchange exchange, String genKey,
UnitMappingEntry unitMapping) {
Flow flow = get(Flow.class, flows, genKey);
if (flow != null)
return flow;
flow = search.findFlow(exchange, unitMapping);
if (flow != null)
flows.put(genKey, flow);
return flow;
}
public Flow findFlow(DataSet dataSet, String genKey,
UnitMappingEntry unitMapping) {
Flow flow = get(Flow.class, flows, genKey);
if (flow != null)
return flow;
flow = search.findFlow(dataSet, unitMapping);
if (flow != null)
flows.put(genKey, flow);
return flow;
}
private <T extends RootEntity> T get(Class<T> type, Map<String, T> cache,
String genKey) {
T entity = cache.get(genKey);
if (entity != null)
return entity;
entity = get(type, genKey);
if (entity != null)
cache.put(genKey, entity);
return entity;
}
public <T extends RootEntity> T get(Class<T> type, String id) {
try {
BaseEntityDao<T> dao = new BaseEntityDao<>(type, database);
return dao.getForRefId(id);
} catch (Exception e) {
log.error("Failed to query database for " + type + " id=" + id, e);
return null;
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T extends AbstractEntity> void put(T entity, String genKey) {
if (entity == null)
return;
try {
Class<T> clazz = (Class<T>) entity.getClass();
database.createDao(clazz).insert(entity);
Map cache = getCache(entity);
if (cache != null)
cache.put(genKey, entity);
} catch (Exception e) {
log.error("Failed to save entity " + entity + " id=" + genKey, e);
}
}
private Map<String, ?> getCache(Object entity) {
if (entity instanceof Actor)
return actors;
if (entity instanceof Source)
return sources;
if (entity instanceof Location)
return locations;
if (entity instanceof Flow)
return flows;
return null;
}
}