All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.openlca.proto.io.server.ResultService Maven / Gradle / Ivy
package org.openlca.proto.io.server;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.openlca.core.database.IDatabase;
import org.openlca.core.io.DbEntityResolver;
import org.openlca.core.library.LibraryDir;
import org.openlca.core.library.reader.LibReaderRegistry;
import org.openlca.core.math.SystemCalculator;
import org.openlca.core.results.LcaResult;
import org.openlca.core.results.providers.ResultProvider;
import org.openlca.core.services.ServerConfig;
import org.openlca.proto.ProtoRef;
import org.openlca.proto.grpc.ImpactFactorRequest;
import org.openlca.proto.grpc.ImpactFactorResponse;
import org.openlca.proto.grpc.ProtoCalculationSetup;
import org.openlca.proto.grpc.ProtoEnviFlow;
import org.openlca.proto.grpc.ProtoResultRef;
import org.openlca.proto.grpc.ProtoTechFlow;
import org.openlca.proto.grpc.ResultServiceGrpc;
import org.openlca.proto.grpc.ResultValue;
import org.openlca.proto.grpc.TechFlowContributionRequest;
import org.openlca.proto.io.input.CalculationSetupReader;
import org.openlca.proto.io.output.Refs;
import com.google.protobuf.Empty;
import io.grpc.Status;
import io.grpc.stub.StreamObserver;
class ResultService extends ResultServiceGrpc.ResultServiceImplBase {
final IDatabase db;
private final LibraryDir libDir;
final Map results = new HashMap<>();
ResultService(ServerConfig config) {
this.db = config.db();
this.libDir = config.dataDir().getLibraryDir();
}
@Override
public void calculate(
ProtoCalculationSetup req, StreamObserver resp) {
var setup = CalculationSetupReader.read(DbEntityResolver.of(db), req);
if (setup == null) {
resp.onError(Status.INVALID_ARGUMENT
.withDescription("invalid calculation setup")
.asException());
return;
}
var result = new SystemCalculator(db)
.withLibraries(LibReaderRegistry.of(db, libDir))
.calculate(setup);
var key = UUID.randomUUID().toString();
results.put(key, result);
var r = ProtoResultRef.newBuilder()
.setId(key)
.build();
resp.onNext(r);
resp.onCompleted();
}
@Override
public void getTechFlows(
ProtoResultRef req, StreamObserver resp) {
var result = results.get(req.getId());
if (result == null) {
Response.notFound(resp, "Result does not exist: " + req.getId());
return;
}
var refData = Refs.dataOf(db);
for (var product : result.techIndex()) {
resp.onNext(Results.toProto(product, refData));
}
resp.onCompleted();
}
@Override
public void getEnviFlows(
ProtoResultRef req, StreamObserver resp) {
var result = results.get(req.getId());
if (result == null) {
Response.notFound(resp, "Result does not exist: " + req.getId());
return;
}
var flows = result.enviIndex();
if (flows == null) {
resp.onCompleted();
return;
}
var refData = Refs.dataOf(db);
for (var flow : flows) {
resp.onNext(Results.toProto(flow, refData));
}
resp.onCompleted();
}
@Override
public void getImpactCategories(
ProtoResultRef req, StreamObserver resp) {
var result = results.get(req.getId());
if (result == null) {
Response.notFound(resp, "Result does not exist: " + req.getId());
return;
}
var impacts = result.impactIndex();
if (impacts == null)
return;
var refData = Refs.dataOf(db);
for (var impact : impacts) {
resp.onNext(Refs.refOf(impact, refData).build());
}
resp.onCompleted();
}
@Override
public void getTotalInventory(
ProtoResultRef req, StreamObserver resp) {
// TODO maybe wrap with `withResult`
var result = results.get(req.getId());
if (result == null) {
Response.notFound(resp, "Result does not exist: " + req.getId());
return;
}
var flows = result.enviIndex();
if (flows == null) {
resp.onCompleted();
return;
}
var refData = Refs.dataOf(db);
for (var flow : flows) {
var value = result.getTotalFlowValueOf(flow);
if (value == 0)
continue;
resp.onNext(Results.toProtoResult(flow, refData, value));
}
resp.onCompleted();
}
@Override
public void getTotalImpacts(
ProtoResultRef req, StreamObserver resp) {
// get the impact results
var result = results.get(req.getId());
if (result == null) {
resp.onCompleted();
return;
}
var impacts = result.impactIndex();
if (impacts == null) {
resp.onCompleted();
return;
}
var refData = Refs.dataOf(db);
for (var impact : impacts) {
var value = result.getTotalImpactValueOf(impact);
var proto = ResultValue.newBuilder()
.setImpact(Refs.refOf(impact, refData))
.setValue(value)
.build();
resp.onNext(proto);
}
resp.onCompleted();
}
@Override
public void getImpactFactors(
ImpactFactorRequest req, StreamObserver resp) {
// check that we have a result with flows and impacts
var result = results.get(req.getResult().getId());
if (result == null) {
resp.onError(Status.INVALID_ARGUMENT
.withDescription("Invalid result ID")
.asException());
return;
}
var flowIndex = result.enviIndex();
var impactIndex = result.impactIndex();
if (flowIndex == null || impactIndex == null) {
resp.onCompleted();
return;
}
// check that we have at least an indicator or flow
var indicator = Results.findImpact(result, req.getIndicator());
var flow = Results.findFlow(result, req.getFlow());
if (flow == null && indicator == null) {
resp.onCompleted();
return;
}
var refData = Refs.dataOf(db);
// get one specific factor of an indicator and flow
if (indicator != null && flow != null) {
var factor = ImpactFactorResponse.newBuilder()
.setIndicator(Refs.refOf(indicator))
.setFlow(Results.toProto(flow, refData))
.setValue(result.getImpactFactorOf(indicator, flow));
resp.onNext(factor.build());
resp.onCompleted();
return;
}
// get non-zero factors of an indicator
if (flow == null) {
var indicatorRef = Refs.refOf(indicator);
for (var iFlow : flowIndex) {
var value = result.getImpactFactorOf(indicator, iFlow);
if (value == 0)
continue;
var factor = ImpactFactorResponse.newBuilder()
.setIndicator(indicatorRef)
.setFlow(Results.toProto(iFlow, refData))
.setValue(value);
resp.onNext(factor.build());
}
resp.onCompleted();
return;
}
// get all impact factors of a flow
for (var impact : impactIndex) {
var factor = ImpactFactorResponse.newBuilder()
.setIndicator(Refs.refOf(impact))
.setFlow(Results.toProto(flow, refData))
.setValue(result.getImpactFactorOf(impact, flow));
resp.onNext(factor.build());
}
resp.onCompleted();
}
@Override
public void getDirectContribution(
TechFlowContributionRequest req, StreamObserver resp) {
TechFlowContribution.of(this, req, resp)
.ifImpact(LcaResult::getDirectImpactOf)
.ifFlow(LcaResult::getDirectFlowOf)
.ifCosts(LcaResult::getDirectCostsOf)
.close();
}
@Override
public void getTotalContribution(
TechFlowContributionRequest req, StreamObserver resp) {
TechFlowContribution.of(this, req, resp)
.ifImpact(LcaResult::getTotalImpactOf)
.ifFlow(LcaResult::getTotalFlowOf)
.ifCosts(LcaResult::getTotalCostsOf)
.close();
}
@Override
public void getTotalContributionOfOne(
TechFlowContributionRequest req,
StreamObserver resp) {
TechFlowContribution.of(this, req, resp)
.ifImpact((result, impact, techFlow) -> {
var productIdx = result.techIndex().of(techFlow);
var impactIdx = result.impactIndex().of(impact);
return result.provider().totalImpactOfOne(impactIdx, productIdx);
})
.ifFlow((result, flow, techFlow) -> {
var productIdx = result.techIndex().of(techFlow);
var flowIdx = result.enviIndex().of(flow);
var value = result.provider().totalFlowOfOne(flowIdx, productIdx);
return ResultProvider.flowValueView(flow, value);
})
.ifCosts((result, techFlow) -> {
var productIdx = result.techIndex().of(techFlow);
return result.provider().totalCostsOfOne(productIdx);
})
.close();
}
@Override
public void dispose(ProtoResultRef req, StreamObserver resp) {
var r = results.remove(req.getId());
if (r != null) {
r.dispose();
}
// we always return ok, even when the result does not exist
resp.onNext(Empty.newBuilder().build());
resp.onCompleted();
}
}