"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const internal_1 = require("../../../internal");
const Storage_1 = require("../../../Storage");
const testHelper_1 = require("../../testHelper");
describe('Cdm/Projection/ProjectionObjectModel', () => {
    const foundationJsonPath = 'cdm:/foundations.cdm.json';
    /**
     * The path between TestDataPath and TestName.
     */
    const testsSubpath = 'Cdm/Projection';
    /**
     * Basic test to save projection based entities and then try to reload them and validate that the projections were persisted correctly
     */
    it('TestProjectionUsingObjectModel', () => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestProjectionUsingObjectModel');
        corpus.storage.mount('local', new Storage_1.LocalAdapter(testHelper_1.testHelper.getActualOutputFolderPath(testsSubpath, 'TestProjectionUsingObjectModel')));
        const localRoot = corpus.storage.fetchRootFolder('local');
        const manifestDefault = createDefaultManifest(corpus, localRoot);
        const entityTestSource = createEntityTestSource(corpus, manifestDefault, localRoot);
        const entityTestEntityProjection = createEntityTestEntityProjection(corpus, manifestDefault, localRoot);
        const entityTestEntityNestedProjection = createEntityTestEntityNestedProjection(corpus, manifestDefault, localRoot);
        const entityTestEntityAttributeProjection = createEntityTestEntityAttributeProjection(corpus, manifestDefault, localRoot);
        const entityTestOperationCollection = createEntityTestOperationCollection(corpus, manifestDefault, localRoot);
        // Save manifest and entities.
        yield manifestDefault.saveAsAsync(`${manifestDefault.manifestName}.manifest.cdm.json`, true);
        const expected = 'TestSource';
        const expectedType = internal_1.cdmObjectType.projectionDef;
        let actual;
        let actualType = internal_1.cdmObjectType.error;
        // Try to read back the newly persisted manifest and projection based entities
        const manifestReadBack = yield corpus.fetchObjectAsync(`local:/${manifestDefault.manifestName}.manifest.cdm.json`);
        expect(manifestReadBack.entities.length)
            .toEqual(5);
        expect(manifestReadBack.entities.allItems[0].entityName)
            .toEqual(entityTestSource.entityName);
        expect(manifestReadBack.entities.allItems[1].entityName)
            .toEqual(entityTestEntityProjection.entityName);
        expect(manifestReadBack.entities.allItems[2].entityName)
            .toEqual(entityTestEntityNestedProjection.entityName);
        expect(manifestReadBack.entities.allItems[3].entityName)
            .toEqual(entityTestEntityAttributeProjection.entityName);
        // Read back the newly persisted manifest and projection based entity TestEntityProjection and validate
        const entityTestEntityProjectionReadBack = yield corpus.fetchObjectAsync(`local:/${entityTestEntityProjection.entityName}.cdm.json/${entityTestEntityProjection.entityName}`, manifestReadBack);
        expect(entityTestEntityProjectionReadBack)
            .toBeTruthy();
        actual = entityTestEntityProjectionReadBack.extendsEntity.explicitReference.source.namedReference;
        actualType = entityTestEntityProjectionReadBack.extendsEntity.explicitReference.getObjectType();
        expect(actual)
            .toEqual(expected);
        expect(actualType)
            .toEqual(expectedType);
        // Read back the newly persisted manifest and projection based entity TestEntityNestedProjection and validate
        const entityTestEntityNestedProjectionReadBack = yield corpus.fetchObjectAsync(`local:/${entityTestEntityNestedProjection.entityName}.cdm.json/${entityTestEntityNestedProjection.entityName}`, manifestReadBack);
        expect(entityTestEntityNestedProjectionReadBack)
            .toBeTruthy();
        actual = entityTestEntityNestedProjectionReadBack.extendsEntity.explicitReference.source.explicitReference.source.explicitReference.source.namedReference;
        actualType = entityTestEntityNestedProjectionReadBack.extendsEntity.explicitReference.source.explicitReference.source.explicitReference.objectType;
        expect(actual)
            .toEqual(expected);
        expect(actualType)
            .toEqual(expectedType);
        // Read back the newly persisted manifest and projection based entity TestEntityAttributeProjection and validate
        const entityTestEntityAttributeProjectionReadBack = yield corpus.fetchObjectAsync(`local:/${entityTestEntityAttributeProjection.entityName}.cdm.json/${entityTestEntityAttributeProjection.entityName}`, manifestReadBack);
        expect(entityTestEntityAttributeProjectionReadBack)
            .toBeTruthy();
        actual = entityTestEntityAttributeProjectionReadBack.attributes.allItems[0].entity.explicitReference.source.namedReference;
        actualType = entityTestEntityAttributeProjectionReadBack.attributes.allItems[0].entity.explicitReference.getObjectType();
        expect(actual)
            .toEqual(expected);
        expect(actualType)
            .toEqual(expectedType);
        // Read back operations collections and validate
        const entityTestOperationCollectionReadBack = yield corpus.fetchObjectAsync(`local:/${entityTestOperationCollection.entityName}.cdm.json/${entityTestOperationCollection.entityName}`, manifestReadBack);
        expect(entityTestOperationCollectionReadBack)
            .toBeTruthy();
        const actualOperationCount = entityTestOperationCollectionReadBack.extendsEntity.explicitReference.operations.length;
        expect(actualOperationCount)
            .toEqual(9);
        const operations = entityTestOperationCollectionReadBack.extendsEntity.explicitReference.operations;
        expect(operations.allItems[0].type)
            .toEqual(internal_1.cdmOperationType.addCountAttribute);
        expect(operations.allItems[1].type)
            .toEqual(internal_1.cdmOperationType.addSupportingAttribute);
        expect(operations.allItems[2].type)
            .toEqual(internal_1.cdmOperationType.addTypeAttribute);
        expect(operations.allItems[3].type)
            .toEqual(internal_1.cdmOperationType.excludeAttributes);
        expect(operations.allItems[4].type)
            .toEqual(internal_1.cdmOperationType.arrayExpansion);
        expect(operations.allItems[5].type)
            .toEqual(internal_1.cdmOperationType.combineAttributes);
        expect(operations.allItems[6].type)
            .toEqual(internal_1.cdmOperationType.renameAttributes);
        expect(operations.allItems[7].type)
            .toEqual(internal_1.cdmOperationType.replaceAsForeignKey);
        expect(operations.allItems[8].type)
            .toEqual(internal_1.cdmOperationType.includeAttributes);
    }));
    /**
     * Create a default manifest
     */
    function createDefaultManifest(corpus, localRoot) {
        const manifestName = 'default';
        const manifestDocName = `${manifestName}.manifest.cdm.json`;
        const manifestDefault = corpus.MakeObject(internal_1.cdmObjectType.manifestDef, manifestName);
        localRoot.documents.push(manifestDefault, manifestDocName);
        return manifestDefault;
    }
    /**
     * Create a simple entity called 'TestSource' with a single attribute
     */
    function createEntityTestSource(corpus, manifestDefault, localRoot) {
        const entityName = 'TestSource';
        const entityTestSource = corpus.MakeObject(internal_1.cdmObjectType.entityDef, entityName);
        const attributeName = 'TestAttribute';
        const entityTestAttribute = corpus.MakeObject(internal_1.cdmObjectType.typeAttributeDef, attributeName, false);
        entityTestAttribute.dataType = corpus.MakeRef(internal_1.cdmObjectType.dataTypeRef, 'string', true);
        entityTestAttribute.purpose = corpus.MakeRef(internal_1.cdmObjectType.purposeRef, 'hasA', true);
        entityTestAttribute.displayName = attributeName;
        entityTestSource.attributes.push(entityTestAttribute);
        const entityTestSourceDoc = corpus.MakeObject(internal_1.cdmObjectType.documentDef, `${entityName}.cdm.json`, false);
        entityTestSourceDoc.imports.push(foundationJsonPath);
        entityTestSourceDoc.definitions.push(entityTestSource);
        localRoot.documents.push(entityTestSourceDoc, entityTestSourceDoc.name);
        manifestDefault.entities.push(entityTestSource);
        return entityTestSource;
    }
    /**
     * Create a simple projection object
     */
    function createProjection(corpus) {
        const projection = corpus.MakeObject(internal_1.cdmObjectType.projectionDef);
        projection.source = corpus.MakeObject(internal_1.cdmObjectType.entityRef, 'TestSource', true);
        return projection;
    }
    /**
     * Create a 3-level nested projection object
     */
    function createNestedProjection(corpus) {
        const projection3 = corpus.MakeObject(internal_1.cdmObjectType.projectionDef);
        projection3.source = corpus.MakeObject(internal_1.cdmObjectType.entityRef, 'TestSource', true);
        const inlineProjectionEntityRef3 = corpus.MakeObject(internal_1.cdmObjectType.entityRef, undefined);
        inlineProjectionEntityRef3.explicitReference = projection3;
        const projection2 = corpus.MakeObject(internal_1.cdmObjectType.projectionDef);
        projection2.source = inlineProjectionEntityRef3;
        const inlineProjectionEntityRef2 = corpus.MakeObject(internal_1.cdmObjectType.entityRef, undefined);
        inlineProjectionEntityRef2.explicitReference = projection2;
        const projection1 = corpus.MakeObject(internal_1.cdmObjectType.projectionDef);
        projection1.source = inlineProjectionEntityRef2;
        return projection1;
    }
    /**
     * Create an entity 'TestEntityProjection' that extends from a projection
     */
    function createEntityTestEntityProjection(corpus, manifestDefault, localRoot) {
        const entityName = 'TestEntityProjection';
        const inlineProjectionEntityRef = corpus.MakeObject(internal_1.cdmObjectType.entityRef, undefined);
        inlineProjectionEntityRef.explicitReference = createProjection(corpus);
        const entityTestEntityProjection = corpus.MakeObject(internal_1.cdmObjectType.entityDef, entityName);
        entityTestEntityProjection.extendsEntity = inlineProjectionEntityRef;
        const entityTestEntityProjectionDoc = corpus.MakeObject(internal_1.cdmObjectType.documentDef, `${entityName}.cdm.json`, false);
        entityTestEntityProjectionDoc.imports.push(foundationJsonPath);
        entityTestEntityProjectionDoc.imports.push('TestSource.cdm.json');
        entityTestEntityProjectionDoc.definitions.push(entityTestEntityProjection);
        localRoot.documents.push(entityTestEntityProjectionDoc, entityTestEntityProjectionDoc.name);
        manifestDefault.entities.push(entityTestEntityProjection);
        return entityTestEntityProjection;
    }
    /**
     * Create an entity 'TestEntityNestedProjection' that extends from a projection
     */
    function createEntityTestEntityNestedProjection(corpus, manifestDefault, localRoot) {
        const entityName = 'TestEntityNestedProjection';
        const inlineProjectionEntityRef = corpus.MakeObject(internal_1.cdmObjectType.entityRef, undefined);
        inlineProjectionEntityRef.explicitReference = createNestedProjection(corpus);
        const entityTestEntityNestedProjection = corpus.MakeObject(internal_1.cdmObjectType.entityDef, entityName);
        entityTestEntityNestedProjection.extendsEntity = inlineProjectionEntityRef;
        const entityTestEntityNestedProjectionDoc = corpus.MakeObject(internal_1.cdmObjectType.documentDef, `${entityName}.cdm.json`, false);
        entityTestEntityNestedProjectionDoc.imports.push(foundationJsonPath);
        entityTestEntityNestedProjectionDoc.imports.push('TestSource.cdm.json');
        entityTestEntityNestedProjectionDoc.definitions.push(entityTestEntityNestedProjection);
        localRoot.documents.push(entityTestEntityNestedProjectionDoc, entityTestEntityNestedProjectionDoc.name);
        manifestDefault.entities.push(entityTestEntityNestedProjection);
        return entityTestEntityNestedProjection;
    }
    /**
     * Create an entity 'TestEntityAttributeProjection' that contains an entity attribute with a projection as a source entity
     */
    function createEntityTestEntityAttributeProjection(corpus, manifestDefault, localRoot) {
        const entityName = 'TestEntityAttributeProjection';
        const inlineProjectionEntityRef = corpus.MakeObject(internal_1.cdmObjectType.entityRef, undefined);
        inlineProjectionEntityRef.explicitReference = createProjection(corpus);
        const entityTestEntityAttributeProjection = corpus.MakeObject(internal_1.cdmObjectType.entityDef, entityName);
        const attributeName = 'TestAttribute';
        const entityTestEntityAttribute = corpus.MakeObject(internal_1.cdmObjectType.entityAttributeDef, attributeName, false);
        entityTestEntityAttribute.entity = inlineProjectionEntityRef;
        entityTestEntityAttributeProjection.attributes.push(entityTestEntityAttribute);
        const entityTestEntityAttributeProjectionDoc = corpus.MakeObject(internal_1.cdmObjectType.documentDef, `${entityName}.cdm.json`, false);
        entityTestEntityAttributeProjectionDoc.imports.push(foundationJsonPath);
        entityTestEntityAttributeProjectionDoc.imports.push('TestSource.cdm.json');
        entityTestEntityAttributeProjectionDoc.definitions.push(entityTestEntityAttributeProjection);
        localRoot.documents.push(entityTestEntityAttributeProjectionDoc, entityTestEntityAttributeProjectionDoc.name);
        manifestDefault.entities.push(entityTestEntityAttributeProjection);
        return entityTestEntityAttributeProjection;
    }
    /**
     * Create a projection object with operations
     */
    function createProjectionWithOperationCollection(corpus, owner) {
        const projection = corpus.MakeObject(internal_1.cdmObjectType.projectionDef);
        projection.source = corpus.MakeObject(internal_1.cdmObjectType.entityRef, 'TestSource', true);
        // AddCountAttribute Operation
        const addCountAttributeOp = new internal_1.CdmOperationAddCountAttribute(corpus.ctx);
        addCountAttributeOp.countAttribute = corpus.MakeObject(internal_1.cdmObjectType.typeAttributeDef, 'countAtt');
        projection.operations.push(addCountAttributeOp);
        // AddSupportingAttribute Operation
        const addSupportingAttributeOp = new internal_1.CdmOperationAddSupportingAttribute(corpus.ctx);
        addSupportingAttributeOp.supportingAttribute = corpus.MakeObject(internal_1.cdmObjectType.typeAttributeDef, 'supportingAtt');
        projection.operations.push(addSupportingAttributeOp);
        // AddTypeAttribute Operation
        const addTypeAttributeOp = new internal_1.CdmOperationAddTypeAttribute(corpus.ctx);
        addTypeAttributeOp.typeAttribute = corpus.MakeObject(internal_1.cdmObjectType.typeAttributeDef, 'typeAtt');
        projection.operations.push(addTypeAttributeOp);
        // ExcludeAttributes Operation
        const excludeAttributesOp = new internal_1.CdmOperationExcludeAttributes(corpus.ctx);
        excludeAttributesOp.excludeAttributes = [];
        excludeAttributesOp.excludeAttributes.push('testAttribute1');
        projection.operations.push(excludeAttributesOp);
        // ArrayExpansion Operation
        const arrayExpansionOp = new internal_1.CdmOperationArrayExpansion(corpus.ctx);
        arrayExpansionOp.startOrdinal = 0;
        arrayExpansionOp.endOrdinal = 1;
        projection.operations.push(arrayExpansionOp);
        // CombineAttributes Operation
        const combineAttributesOp = new internal_1.CdmOperationCombineAttributes(corpus.ctx);
        combineAttributesOp.select = [];
        combineAttributesOp.mergeInto = corpus.MakeObject(internal_1.cdmObjectType.typeAttributeDef, 'combineAtt');
        combineAttributesOp.select.push('testAttribute1');
        projection.operations.push(combineAttributesOp);
        // RenameAttributes Operation
        const renameAttributesOp = new internal_1.CdmOperationRenameAttributes(corpus.ctx);
        renameAttributesOp.renameFormat = '{m}';
        projection.operations.push(renameAttributesOp);
        // ReplaceAsForeignKey Operation
        const replaceAsForeignKeyOp = new internal_1.CdmOperationReplaceAsForeignKey(corpus.ctx);
        replaceAsForeignKeyOp.reference = 'testAttribute1';
        replaceAsForeignKeyOp.replaceWith = corpus.MakeObject(internal_1.cdmObjectType.typeAttributeDef, 'testForeignKey', false);
        projection.operations.push(replaceAsForeignKeyOp);
        // IncludeAttributes Operation
        const includeAttributesOp = new internal_1.CdmOperationIncludeAttributes(corpus.ctx);
        includeAttributesOp.includeAttributes = [];
        includeAttributesOp.includeAttributes.push('testAttribute1');
        projection.operations.push(includeAttributesOp);
        return projection;
    }
    /**
     * Create an entity 'TestOperationCollection' that extends from a projection with a collection of operations
     */
    function createEntityTestOperationCollection(corpus, manifestDefault, localRoot) {
        const entityName = 'TestOperationCollection';
        const inlineProjectionEntityRef = corpus.MakeObject(internal_1.cdmObjectType.entityRef, undefined);
        const entityTestOperationCollection = corpus.MakeObject(internal_1.cdmObjectType.entityDef, entityName);
        inlineProjectionEntityRef.explicitReference = createProjectionWithOperationCollection(corpus, entityTestOperationCollection);
        entityTestOperationCollection.extendsEntity = inlineProjectionEntityRef;
        const entityTestOperationCollectionDoc = corpus.MakeObject(internal_1.cdmObjectType.documentDef, `${entityName}.cdm.json`, false);
        entityTestOperationCollectionDoc.imports.push(foundationJsonPath);
        entityTestOperationCollectionDoc.imports.push('TestSource.cdm.json');
        entityTestOperationCollectionDoc.definitions.push(entityTestOperationCollection);
        localRoot.documents.push(entityTestOperationCollectionDoc, entityTestOperationCollectionDoc.name);
        manifestDefault.entities.push(entityTestOperationCollection);
        return entityTestOperationCollection;
    }
});
//# sourceMappingURL=ProjectionObjectModel.test.js.map