Skip to content

Commit

Permalink
Merge pull request #898 from mff-uk/feature/model-update
Browse files Browse the repository at this point in the history
Feature/model update
  • Loading branch information
skodapetr authored Feb 5, 2025
2 parents 70a5322 + 05647a8 commit 11b06cd
Show file tree
Hide file tree
Showing 21 changed files with 1,709 additions and 641 deletions.
6 changes: 3 additions & 3 deletions packages/core-v2/src/entity-model/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Entity model

Contains implementation and interfaces for supporting entity models.

An entity model is a model that organizes its data into entities. An entity is a collection of data that is uniquely
identifiable by an ID. In JS, entity is represented as a JSON serializable object.
An entity model is a model that organizes its data into entities.
An entity is a collection of data that is uniquely identifiable by an identifier.
In JavaScript, entity is represented as a JSON serializable object.
11 changes: 7 additions & 4 deletions packages/core-v2/src/entity-model/entity-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import { Entities, Entity } from "./entity";
* @example Semantic model that contains entities such as classes, relations, generalizations, etc.
*/
export interface EntityModel {

/**
* Returns all entities in the model.
* Entity is a JSON object with a unique ID. That is the only requirement.
* Entity is a JSON object with a unique ID.
* That is the only requirement.
*/
getEntities(): Entities;

Expand All @@ -23,17 +25,18 @@ export interface EntityModel {
subscribeToChanges(callback: (updated: Record<string, Entity>, removed: string[]) => void): () => void;

/**
* Returns Id of the model
* returns internal model identifier
*/
getId(): string;

/**
* Returns the alias of the model
* @returns human readable alias of the model
*/
getAlias(): string | null;

/**
* Sets the alias of the model
* Sets the alias of the model.
*/
setAlias(alias: string | null): void;

}
15 changes: 11 additions & 4 deletions packages/core-v2/src/entity-model/entity.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@

export type EntityIdentifier = string;

/**
* A JSON serializable object that represents an entity.
* @example Semantic class, relation, generalization, etc.
* Each entity is identified by its unique ID.
*
* @example Semantic class, relation, generalization, etc.
*/
export interface Entity {
id: string;

id: EntityIdentifier;

type: string[];

}

/**
* Object containing {@link Entity}s by their iri as a key
* Object containing {@link Entity}s by their iri as a key.
*/
export type Entities = Record<string, Entity>;
export type Entities = Record<string, Entity>;
83 changes: 73 additions & 10 deletions packages/core-v2/src/semantic-model/aggregator/aggregator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { EntityModel } from "../../entity-model/entity-model";
import { VisualEntity } from "../../visual-model/visual-entity";
import { VisualModel, isVisualModel } from "../../visual-model/visual-model";
import { SEMANTIC_MODEL_CLASS, SEMANTIC_MODEL_GENERALIZATION, SEMANTIC_MODEL_RELATIONSHIP, SemanticModelClass, SemanticModelRelationship, isSemanticModelClass, isSemanticModelGeneralization, isSemanticModelRelationship } from "../concepts";
import { createDefaultProfileEntityAggregator, ProfileEntityAggregator } from "../profile/aggregator/aggregator";
import { isSemanticModelClassProfile, isSemanticModelRelationshipProfile } from "../profile/concepts";
import { SemanticModelClassUsage, SemanticModelRelationshipUsage, isSemanticModelClassUsage, isSemanticModelRelationshipUsage } from "../usage/concepts";

/**
Expand Down Expand Up @@ -33,6 +35,8 @@ export interface AggregatedEntityWrapper {
/**
* Visual information about the entity that was obtained from the visual model.
* There is no aggregation of visual entities as only one visual model can be present.
*
* @deprecated
*/
visualEntity: VisualEntity | null;
}
Expand Down Expand Up @@ -94,8 +98,17 @@ class SemanticModelAggregatorInternal implements SemanticModelAggregator {

baseModelSubscribers = new Set<AggregatedModelSubscriber>();

/**
* @deprecated
*/
activeVisualModel: VisualModel | null = null;

/**
* Profile aggregator.
*/
profileEntityAggregator: ProfileEntityAggregator =
createDefaultProfileEntityAggregator();

addModel(model: SupportedModels) {
if (this.models.has(model)) {
throw new Error("Model already added.");
Expand Down Expand Up @@ -152,19 +165,21 @@ class SemanticModelAggregatorInternal implements SemanticModelAggregator {
}

private getEntityDependencies(entity: Entity | null): string[] {
if (!entity) {
if (entity === null) {
return [];
}

if (isSemanticModelClassUsage(entity) || isSemanticModelRelationshipUsage(entity)) {
return [entity.usageOf];
}

// Special handling of selected entity types.
if (isSemanticModelClass(entity) || isSemanticModelRelationship(entity) || isSemanticModelGeneralization(entity)) {
return [];
}

console.warn("Entity", entity.id, "has an unknown type", entity.type , ", and therefore the aggregator does not know its dependencies. The entity would be considered as standalone and not aggregated with other entities. This may lead to unexpected results if you expect something else.");
const profileDependencies = this.profileEntityAggregator.dependencies(entity);
if (profileDependencies !== null) {
return profileDependencies;
}

console.warn("Entity", entity.id, "has an unknown type", entity.type, ", and therefore the aggregator does not know its dependencies. The entity would be considered as standalone and not aggregated with other entities. This may lead to unexpected results if you expect something else.");
return [];
}

Expand Down Expand Up @@ -202,9 +217,45 @@ class SemanticModelAggregatorInternal implements SemanticModelAggregator {
if (removed.includes(updatedEntity)) {
delete this.baseModelEntities[updatedEntity];
} else {
const {entity, model} = this.entityCache[updatedEntity]!;
const { entity, model } = this.entityCache[updatedEntity]!;

if (isSemanticModelClassProfile(entity)) {
const dependencies = (this.profileEntityAggregator.dependencies(entity) ?? [])
.map(identifier => this.baseModelEntities[identifier])
.filter(item => item !== undefined);

const aggregatedDependencies =
dependencies.map(item => item.aggregatedEntity)
.filter(item => item !== null)
.filter(item => isSemanticModelClassProfile(item) || isSemanticModelClass(item));

this.baseModelEntities[updatedEntity] = {
id: updatedEntity,
aggregatedEntity: this.profileEntityAggregator.aggregateSemanticModelClassProfile(
entity, aggregatedDependencies),
rawEntity: entity,
sources: dependencies,
visualEntity: null,
};
} else if (isSemanticModelRelationshipProfile(entity)) {
const dependencies = (this.profileEntityAggregator.dependencies(entity) ?? [])
.map(identifier => this.baseModelEntities[identifier])
.filter(item => item !== undefined);

if (
const aggregatedDependencies =
dependencies.map(item => item.aggregatedEntity)
.filter(item => item !== null)
.filter(item => isSemanticModelRelationshipProfile(item) || isSemanticModelRelationship(item));

this.baseModelEntities[updatedEntity] = {
id: updatedEntity,
aggregatedEntity: this.profileEntityAggregator.aggregateSemanticModelRelationshipProfile(
entity, aggregatedDependencies),
rawEntity: entity,
sources: dependencies,
visualEntity: null,
};
} else if (
isSemanticModelClassUsage(entity)
) {
const source = this.baseModelEntities[entity.usageOf];
Expand Down Expand Up @@ -261,7 +312,7 @@ class SemanticModelAggregatorInternal implements SemanticModelAggregator {
!entity.type.includes(SEMANTIC_MODEL_GENERALIZATION) &&
!entity.type.includes(SEMANTIC_MODEL_RELATIONSHIP)
) {
console.warn("Entity", entity.id, "from model", model.getId(), "has an unknown type", entity.type , ", and therefore the aggregator does not know its dependencies. The entity would be considered as standalone and not aggregated with other entities. This may lead to unexpected results if you expect something else.");
console.warn("Entity", entity.id, "from model", model.getId(), "has an unknown type", entity.type, ", and therefore the aggregator does not know its dependencies. The entity would be considered as standalone and not aggregated with other entities. This may lead to unexpected results if you expect something else.");
}
this.baseModelEntities[updatedEntity] = {
id: updatedEntity,
Expand All @@ -285,6 +336,9 @@ class SemanticModelAggregatorInternal implements SemanticModelAggregator {
return new SemanticModelAggregatorView(this);
}

/**
* @deprecated
*/
setActiveVisualModel(toModel: string | VisualModel | null) {
if (typeof toModel == "string") {
const availableModels = [...this.models.keys()];
Expand Down Expand Up @@ -329,7 +383,7 @@ export class SemanticModelAggregatorView {
* @returns Dictionary with all entities aggregated.
*/
getEntities(): Record<string, AggregatedEntityWrapper> {
const entities = {...this.aggregator.baseModelEntities};
const entities = { ...this.aggregator.baseModelEntities };
// Just an optimization to not call it multiple times, when it is null.
if (this.aggregator.activeVisualModel === null) {
return entities;
Expand Down Expand Up @@ -361,14 +415,23 @@ export class SemanticModelAggregatorView {
return this.aggregator.activeVisualModel?.getIdentifier();
}

/**
* @deprecated
*/
getActiveVisualModel() {
return this.aggregator.activeVisualModel;
}

/**
* @deprecated
*/
changeActiveVisualModel(identifier: string | null) {
this.aggregator.setActiveVisualModel(identifier);
}

/**
* @deprecated
*/
getAvailableVisualModels(): VisualModel[] {
return [...this.aggregator.models.keys()]
.filter((m) => isVisualModel(m)) as VisualModel[];
Expand Down
6 changes: 3 additions & 3 deletions packages/core-v2/src/semantic-model/operations/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function createClass(entity: Partial<Omit<SemanticModelClass, "type">> =

const MODIFY_CLASS_OPERATION = 'modify';

interface ModifyClassOperation extends Operation {
export interface ModifyClassOperation extends Operation {
type: typeof MODIFY_CLASS_OPERATION;
id: string;
entity: Partial<Omit<SemanticModelClass, "type" | "id">>;
Expand Down Expand Up @@ -83,7 +83,7 @@ export function createRelationship(entity: Partial<Omit<SemanticModelRelationshi

const MODIFY_RELATIONSHIP_OPERATION = 'modify-relation';

interface ModifyRelationOperation extends Operation {
export interface ModifyRelationOperation extends Operation {
type: typeof MODIFY_RELATIONSHIP_OPERATION;
id: string;
entity: Partial<Omit<SemanticModelRelationship, "type" | "id">>;
Expand Down Expand Up @@ -150,7 +150,7 @@ const DELETE_ENTITY_OPERATION = 'delete';
/**
* Deletes any type of entity from the single model.
*/
interface DeleteEntityOperation extends Operation {
export interface DeleteEntityOperation extends Operation {
type: typeof DELETE_ENTITY_OPERATION;
id: string;
}
Expand Down
Loading

0 comments on commit 11b06cd

Please sign in to comment.