huridocs/uwazi

View on GitHub
app/api/entities.v2/services/EntityRelationshipsUpdateService.ts

Summary

Maintainability
A
0 mins
Test Coverage
A
95%
import { MatchQueryNode } from 'api/relationships.v2/model/MatchQueryNode';
import { Template } from 'api/templates.v2/model/Template';
import { RelationshipProperty } from 'api/templates.v2/model/RelationshipProperty';
import { RelationshipsDataSource } from 'api/relationships.v2/contracts/RelationshipsDataSource';
import { TemplatesDataSource } from 'api/templates.v2/contracts/TemplatesDataSource';
import { Entity, EntityMetadata } from '../model/Entity';
import { EntitiesDataSource } from '../contracts/EntitiesDataSource';

export class EntityRelationshipsUpdateService {
  private entitiesDataSource: EntitiesDataSource;

  private templatesDataSource: TemplatesDataSource;

  private relationshipsDataSource: RelationshipsDataSource;

  constructor(
    entitiesDataSource: EntitiesDataSource,
    templatesDataSource: TemplatesDataSource,
    relatioshipsDataSource: RelationshipsDataSource
  ) {
    this.entitiesDataSource = entitiesDataSource;
    this.templatesDataSource = templatesDataSource;
    this.relationshipsDataSource = relatioshipsDataSource;
  }

  private async buildInheritedInformation(property: RelationshipProperty, entity: Entity) {
    if (property.denormalizedProperty) {
      const denormalizedProperty = await this.templatesDataSource.getPropertyByName(
        property.denormalizedProperty
      );

      return {
        inheritedValue: entity.metadata[denormalizedProperty.name] ?? [],
        inheritedType: denormalizedProperty.type,
      };
    }
    return {};
  }

  private async transformToDenormalizedData(
    property: RelationshipProperty,
    queryResult: Entity[]
  ): Promise<EntityMetadata[]> {
    return Promise.all(
      queryResult.map(async entity => ({
        value: entity.sharedId,
        label: entity.title,
        ...(await this.buildInheritedInformation(property, entity)),
      }))
    );
  }

  private async findTemplate(currentTemplate: Template | undefined, id: string) {
    if (currentTemplate?.id === id) return currentTemplate;

    const foundTemplate = await this.templatesDataSource.getById(id);
    if (!foundTemplate) {
      throw new Error('Template does not exist');
    }
    return foundTemplate;
  }

  async update(sharedIds: string[]) {
    let template: Template | undefined;
    await this.entitiesDataSource.getByIds(sharedIds).forEach(async entity => {
      template = await this.findTemplate(template, entity.template);

      const metadataToUpdate: Record<string, EntityMetadata[]> = {};

      await Promise.all(
        template.properties.map(async property => {
          if (
            property instanceof RelationshipProperty &&
            entity.obsoleteMetadata.includes(property.name)
          ) {
            const results = await this.relationshipsDataSource
              .getByQuery(
                new MatchQueryNode({ sharedId: entity.sharedId }, property.query),
                entity.language
              )
              .all();

            metadataToUpdate[property.name] = await this.transformToDenormalizedData(
              property,
              results
            );
          }
        })
      );

      await this.entitiesDataSource.updateObsoleteMetadataValues(entity._id, metadataToUpdate);
    });
  }
}