// (C) 2007-2019 GoodData Corporation import { ExecuteAFM as AFM } from "@gooddata/typings"; import { includes } from "lodash"; import { ISchema } from "../../schema/model/Schema"; import { IMockProject, getMetrics, getAttributeDisplayForms, getDateAttributes, getAttributeByTitle, } from "../../model/MockProject"; import { buildProject } from "../../schema/builder"; export class AFMBuilder { public static buildFromSchema(schema: ISchema) { return new AFMBuilder(buildProject(schema)); } private measures: AFM.IMeasure[] = []; private attributes: AFM.IAttribute[] = []; private filters: AFM.ExtendedFilter[] = []; private sorts: AFM.SortItem[] = []; private resultSpec: AFM.IResultSpec = {}; private nativeTotals: AFM.INativeTotalItem[]; public constructor(private project: IMockProject) {} public addMeasure( format?: string, alias?: string, computeRatio?: boolean, index: number = this.measures.length, ) { const metrics = getMetrics(this.project); const measure: AFM.IMeasure = { localIdentifier: `m${index}`, definition: { measure: { item: { identifier: metrics[index].meta.identifier, }, computeRatio, }, }, }; if (format) { measure.format = format; } if (alias) { measure.alias = alias; } this.measures.push(measure); return this; } public addAttributeBasedMeasure() { const displayForms = getAttributeDisplayForms(this.project); const measure: AFM.IMeasure = { localIdentifier: `m${this.measures.length}`, alias: `Count of ${displayForms[0].meta.title}`, definition: { measure: { aggregation: "count", item: { identifier: displayForms[0].meta.identifier, }, }, }, format: "#,##0", }; this.measures.push(measure); return this; } public addAttribute(alias?: string) { const displayForms = getAttributeDisplayForms(this.project); const attribute: AFM.IAttribute = { localIdentifier: `a${this.attributes.length}`, displayForm: { identifier: displayForms[this.attributes.length].meta.identifier, }, }; if (alias) { attribute.alias = alias; } this.attributes.push(attribute); return this; } public addAttributeByTitle(title: string) { const attribute = getAttributeByTitle(this.project, title); const displayForms = attribute.content.displayForms; this.attributes.push({ localIdentifier: `a${this.attributes.length}`, displayForm: { identifier: displayForms[displayForms.length - 1].meta.identifier, }, }); return this; } public addDateAttribute(granularity: string = "GDC.time.year") { const dateAttribute = getDateAttributes(this.project).find(dateAttribute => { return dateAttribute.type === granularity; }); this.attributes.push({ localIdentifier: `a${this.attributes.length}`, displayForm: { identifier: dateAttribute.displayForms[0].meta.identifier, }, }); return this; } public addFilter(filter: AFM.ExtendedFilter) { this.filters.push(filter); return this; } public addSortByAttribute(index: number, direction: AFM.SortDirection = "asc") { const sortObject: AFM.IAttributeSortItem = { attributeSortItem: { attributeIdentifier: `a${index}`, direction, }, }; this.sorts.push(sortObject); return this; } public addSortByMeasure(index: number, direction: AFM.SortDirection = "asc") { const sortObject: AFM.IMeasureSortItem = { measureSortItem: { direction, locators: [ { measureLocatorItem: { measureIdentifier: `m${index}`, }, }, ], }, }; this.sorts.push(sortObject); return this; } public addResultSpec(resultSpec: AFM.IResultSpec) { this.resultSpec = resultSpec; return this; } public addTotals(totalTypes: AFM.TotalType[]) { let nativeTotals: AFM.INativeTotalItem[]; const totals: AFM.ITotalItem[] = []; const attributeIdentifier: AFM.Identifier = this.attributes[0].localIdentifier; totalTypes.forEach(type => { this.measures.forEach(measure => { totals.push({ measureIdentifier: measure.localIdentifier, attributeIdentifier, type, }); }); }); if (includes(totalTypes, "nat")) { nativeTotals = this.measures.map(measure => ({ measureIdentifier: measure.localIdentifier, attributeIdentifiers: [], })); } this.resultSpec.dimensions[0].totals = totals; this.nativeTotals = nativeTotals; return this; } public build(): AFM.IExecution { const afmResult: AFM.IExecution = { execution: { afm: { measures: this.measures, attributes: this.attributes, filters: this.filters, nativeTotals: this.nativeTotals, }, resultSpec: this.resultSpec, }, }; if (this.sorts.length > 0) { afmResult.execution.resultSpec.sorts = this.sorts; } return afmResult; } }