Select Git revision
-
Lucas Fernandes de Oliveira authored
Signed-off-by:
Lucas Fernandes de Oliveira <lfo14@inf.ufpr.br>
Lucas Fernandes de Oliveira authoredSigned-off-by:
Lucas Fernandes de Oliveira <lfo14@inf.ufpr.br>
engine.ts 3.65 KiB
/*
* Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre
* Departamento de Informatica - Universidade Federal do Parana
*
* This file is part of blend.
*
* blend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* blend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with blend. If not, see <http://www.gnu.org/licenses/>.
*/
import { Dimension } from "./dimension";
import { Metric } from "./metric";
import { View } from "./view";
import { Query } from "../common/query";
import { Graph } from "../util/graph";
export class Engine {
private views: View[] = [];
private metrics: Metric[] = [];
private dimensions: Dimension[] = [];
private graph: Graph;
constructor () {
this.views = [];
this.metrics = [];
this.dimensions = [];
this.graph = new Graph();
}
public getViews() {
return this.views;
}
public addView(view: View) {
if (this.graph.addView(view)) {
this.views.push(view);
return view;
}
return null;
}
public addMetric(metric: Metric) {
if (this.graph.addMetric(metric)) {
this.metrics.push(metric);
return metric;
}
return null;
}
public getMetricByName(name: string) {
let result = this.metrics.find(metric => metric.name === name);
if (!result) {
throw new Error("The metric named " + name + " was not found");
}
return result;
}
public addDimension(dimension: Dimension) {
if (this.graph.addDimension(dimension)) {
this.dimensions.push(dimension);
return dimension;
}
return null;
}
public getDimensionByName(name: string) {
let result = this.dimensions.find(dimension => dimension.name === name);
if (!result) {
throw new Error("The dimension named " + name + " was not found");
}
return result;
}
public query (q: Query) {
return this.selectOptimalView(q);
}
private selectOptimalView (q: Query) {
let optimalViews = this.graph.cover(q.metrics, q.dimensions);
if (optimalViews.length === 0) {
throw new Error ("Engine views cannot cover the query");
}
// If all the metrics and dimensions are the same and only exist one child view
// return this single child view
if (optimalViews.length === 1 &&
optimalViews[0].view.metrics.length === q.metrics.length &&
optimalViews[0].view.dimensions.length === q.dimensions.length &&
optimalViews[0].view.metrics.every((item) => q.metrics.indexOf(item) !== -1) &&
optimalViews[0].view.dimensions.every((item) => q.dimensions.indexOf(item) !== -1)) {
return optimalViews[0].view;
}
else {
let options = {
metrics: q.metrics,
dimensions: q.dimensions,
materialized: false,
origin: false, // Never a dynamic generated view will be origin
childViews: optimalViews
};
let view = new View(options);
this.addView(view);
return view;
}
}
}