in src/app/template/index.ts [165:353]
public addObject(table: string, objectClass: Prototypes.ObjectClass) {
// Visit a object only once
if (this.objectVisited[objectClass.object._id]) {
return;
}
this.objectVisited[objectClass.object._id] = true;
const template = this.template;
// Get template inference data
const params = objectClass.getTemplateParameters();
if (params && params.inferences) {
for (const inference of params.inferences) {
if (inference.axis) {
this.addColumnsFromExpression(
inference.dataSource.table,
inference.axis.expression
);
}
if (inference.scale) {
// Find all objects that use the scale
const expressions = new Set<string>();
let table: string = null;
let groupBy: Specification.Types.GroupBy = null;
for (const item of Prototypes.forEachObject(
this.template.specification
)) {
for (const [, mapping] of Prototypes.forEachMapping(
item.object.mappings
)) {
if (mapping.type == MappingType.scale) {
const scaleMapping = mapping as Specification.ScaleMapping;
if (scaleMapping.scale == inference.objectID) {
expressions.add(scaleMapping.expression);
if (item.kind == "glyph" || item.kind == "mark") {
table = item.glyph.table;
// Find the plot segment
for (const ps of Prototypes.forEachObject(
this.template.specification
)) {
if (
ps.kind == "chart-element" &&
Prototypes.isType(ps.object.classID, "plot-segment") &&
item.glyph._id === (ps.chartElement as any).glyph
) {
groupBy = (ps.chartElement as Specification.PlotSegment)
.groupBy;
break; // TODO: for now, we assume it's the first one
}
}
} else if (
item.kind == "chart-element" &&
Prototypes.isType(
item.chartElement.classID,
"legend.custom"
)
) {
// don't add column names legend expression into inferences
expressions.delete(scaleMapping.expression);
} else if (
item.kind == "chart-element" &&
Prototypes.isType(item.chartElement.classID, "links")
) {
const linkTable = item.object.properties.linkTable as any;
const defaultTable = this.dataset.tables[0];
table = (linkTable && linkTable.table) || defaultTable.name;
} else {
table = this.dataset.tables.find(
(table) => table.type === TableType.Main
).name;
}
}
}
}
}
if (expressions.size == 0) {
// Scale not used
continue;
}
inference.scale.expressions = Array.from(expressions);
if (!inference.dataSource) {
inference.dataSource = {
table,
groupBy,
};
}
}
if (inference.expression) {
this.addColumnsFromExpression(
inference.dataSource.table,
inference.expression.expression
);
}
if (inference.nestedChart) {
const { nestedChart } = inference;
Object.keys(nestedChart.columnNameMap).forEach((key) => {
this.addColumn(inference.dataSource.table, key);
});
}
if (inference.axis) {
const templateObject = Prototypes.findObjectById(
this.chart,
inference.objectID
);
if (
(templateObject.properties[
inference.axis.property as string
] as any).autoDomainMin !== "undefined"
) {
inference.autoDomainMin = (templateObject.properties[
inference.axis.property as string
] as any).autoDomainMin as boolean;
}
if (
(templateObject.properties[
inference.axis.property as string
] as any).autoDomainMax !== "undefined"
) {
inference.autoDomainMax = (templateObject.properties[
inference.axis.property as string
] as any).autoDomainMax as boolean;
}
if (inference.autoDomainMax === undefined) {
inference.autoDomainMax = true;
}
if (inference.autoDomainMax === undefined) {
inference.autoDomainMax = true;
}
}
template.inference.push(inference);
}
}
if (params && params.properties) {
for (const property of params.properties) {
// Make a default display name
let pn = "";
if (property.target.property) {
pn = this.propertyToString(property.target.property);
} else if (property.target.attribute) {
pn = property.target.attribute;
}
property.displayName = objectClass.object.properties.name + "/" + pn;
template.properties.push(property);
}
}
// Add filter
const plotSegmentObj = objectClass.object as Specification.PlotSegment<any>;
if (Prototypes.isType(plotSegmentObj.classID, "plot-segment")) {
this.addTable(plotSegmentObj.table);
const filter = plotSegmentObj.filter;
if (filter) {
const { categories, expression } = filter;
if (expression) {
this.addColumnsFromExpression(table, expression);
}
if (categories) {
this.addColumnsFromExpression(table, categories.expression);
}
}
const groupBy = plotSegmentObj.groupBy;
if (groupBy && groupBy.expression) {
this.addColumnsFromExpression(table, groupBy.expression);
}
}
// Get mappings
for (const [, mapping] of Prototypes.forEachMapping(
objectClass.object.mappings
)) {
if (mapping.type == MappingType.scale) {
const scaleMapping = mapping as Specification.ScaleMapping;
this.addColumnsFromExpression(
scaleMapping.table,
scaleMapping.expression
);
}
if (mapping.type == MappingType.text) {
const textMapping = mapping as Specification.TextMapping;
this.addColumnsFromExpression(
textMapping.table,
textMapping.textExpression,
true
);
}
}
}