mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-27 00:31:42 +00:00
parent
bf25787709
commit
c56e78f3f2
@ -408,6 +408,7 @@ public abstract class EntityRepository<T> {
|
||||
T original = setFields(dao.findEntityById(id), patchFields);
|
||||
|
||||
// Apply JSON patch to the original entity to get the updated entity
|
||||
System.out.println("XXX patch is " + patch);
|
||||
T updated = JsonUtils.applyPatch(original, patch, entityClass);
|
||||
EntityInterface<T> updatedEntity = getEntityInterface(updated);
|
||||
updatedEntity.setUpdateDetails(user, System.currentTimeMillis());
|
||||
@ -861,6 +862,14 @@ public abstract class EntityRepository<T> {
|
||||
return daoCollection.relationshipDAO().insert(fromId, toId, fromEntity, toEntity, relationship.ordinal());
|
||||
}
|
||||
|
||||
public int addBidirectionalRelationship(
|
||||
UUID fromId, UUID toId, String fromEntity, String toEntity, Relationship relationship) {
|
||||
if (fromId.compareTo(toId) < 0) {
|
||||
return daoCollection.relationshipDAO().insert(fromId, toId, fromEntity, toEntity, relationship.ordinal());
|
||||
}
|
||||
return daoCollection.relationshipDAO().insert(toId, fromId, toEntity, fromEntity, relationship.ordinal());
|
||||
}
|
||||
|
||||
public void setOwner(UUID ownedEntityId, String ownedEntityType, EntityReference owner) {
|
||||
// Add relationship owner --- owns ---> ownedEntity
|
||||
if (owner != null) {
|
||||
@ -891,6 +900,26 @@ public abstract class EntityRepository<T> {
|
||||
.findTo(fromId.toString(), fromEntity, relationship.ordinal(), toEntity, deleted);
|
||||
}
|
||||
|
||||
public void validateUsers(List<EntityReference> entityReferences) throws IOException {
|
||||
if (entityReferences != null) {
|
||||
entityReferences.sort(EntityUtil.compareEntityReference);
|
||||
for (EntityReference entityReference : entityReferences) {
|
||||
EntityReference ref = daoCollection.userDAO().findEntityReferenceById(entityReference.getId());
|
||||
entityReference.withType(ref.getType()).withName(ref.getName()).withDisplayName(ref.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void validateRoles(List<EntityReference> entityReferences) throws IOException {
|
||||
if (entityReferences != null) {
|
||||
entityReferences.sort(EntityUtil.compareEntityReference);
|
||||
for (EntityReference entityReference : entityReferences) {
|
||||
EntityReference ref = daoCollection.roleDAO().findEntityReferenceById(entityReference.getId());
|
||||
entityReference.withType(ref.getType()).withName(ref.getName()).withDisplayName(ref.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Operation {
|
||||
PUT,
|
||||
PATCH,
|
||||
@ -1135,6 +1164,77 @@ public abstract class EntityRepository<T> {
|
||||
return !addedItems.isEmpty() || !deletedItems.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove `fromEntityType:fromId` -- `relationType` ---> `toEntityType:origToRefs` Add `fromEntityType:fromId` --
|
||||
* `relationType` ---> `toEntityType:updatedToRefs` and record it as change for entity field `field`.
|
||||
*/
|
||||
public final void updateToRelationships(
|
||||
String field,
|
||||
String fromEntityType,
|
||||
UUID fromId,
|
||||
Relationship relationshipType,
|
||||
String toEntityType,
|
||||
List<EntityReference> origToRefs,
|
||||
List<EntityReference> updatedToRefs)
|
||||
throws JsonProcessingException {
|
||||
List<EntityReference> added = new ArrayList<>();
|
||||
List<EntityReference> deleted = new ArrayList<>();
|
||||
if (!recordListChange(field, origToRefs, updatedToRefs, added, deleted, entityReferenceMatch)) {
|
||||
// No changes between original and updated.
|
||||
return;
|
||||
}
|
||||
// Remove relationships from original
|
||||
daoCollection
|
||||
.relationshipDAO()
|
||||
.deleteFrom(fromId.toString(), fromEntityType, relationshipType.ordinal(), toEntityType);
|
||||
// Add relationships from updated
|
||||
for (EntityReference ref : updatedToRefs) {
|
||||
System.out.println(
|
||||
String.format(
|
||||
"XXX relationship %s:%s to %s:%s of type %s",
|
||||
fromEntityType, fromId, toEntityType, ref.getId(), relationshipType));
|
||||
addRelationship(fromId, ref.getId(), fromEntityType, toEntityType, relationshipType);
|
||||
}
|
||||
updatedToRefs.sort(EntityUtil.compareEntityReference);
|
||||
origToRefs.sort(EntityUtil.compareEntityReference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove `fromEntityType:origFromRefs` -- `relationType` ---> `toEntityType:toId` Add
|
||||
* `fromEntityType:updatedFromRefs` -- `relationType` ---> `toEntityType:toId` and record it as change for entity
|
||||
* field `field`.
|
||||
*/
|
||||
public final void updateFromRelationships(
|
||||
String field,
|
||||
String fromEntityType,
|
||||
List<EntityReference> originFromRefs,
|
||||
List<EntityReference> updatedFromRefs,
|
||||
Relationship relationshipType,
|
||||
String toEntityType,
|
||||
UUID toId)
|
||||
throws JsonProcessingException {
|
||||
List<EntityReference> added = new ArrayList<>();
|
||||
List<EntityReference> deleted = new ArrayList<>();
|
||||
if (!recordListChange(field, originFromRefs, updatedFromRefs, added, deleted, entityReferenceMatch)) {
|
||||
// No changes between original and updated.
|
||||
return;
|
||||
}
|
||||
// Remove relationships from original
|
||||
daoCollection
|
||||
.relationshipDAO()
|
||||
.deleteTo(toId.toString(), fromEntityType, relationshipType.ordinal(), toEntityType);
|
||||
// Add relationships from updated
|
||||
for (EntityReference ref : updatedFromRefs) {
|
||||
System.out.println(
|
||||
String.format(
|
||||
"XXX relationship %s:%s to %s:%s of type %s",
|
||||
fromEntityType, ref, toEntityType, toId, relationshipType));
|
||||
addRelationship(ref.getId(), toId, fromEntityType, toEntityType, relationshipType);
|
||||
}
|
||||
updatedFromRefs.sort(EntityUtil.compareEntityReference);
|
||||
originFromRefs.sort(EntityUtil.compareEntityReference);
|
||||
}
|
||||
|
||||
public final void storeUpdate() throws IOException {
|
||||
if (updateVersion(original.getVersion())) { // Update changed the entity version
|
||||
storeOldVersion(); // Store old version for listing previous versions of the entity
|
||||
|
||||
@ -19,10 +19,13 @@ package org.openmetadata.catalog.jdbi3;
|
||||
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
|
||||
import static org.openmetadata.catalog.Entity.helper;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import org.jdbi.v3.sqlobject.transaction.Transaction;
|
||||
import org.openmetadata.catalog.Entity;
|
||||
@ -30,6 +33,7 @@ import org.openmetadata.catalog.entity.data.Glossary;
|
||||
import org.openmetadata.catalog.resources.glossary.GlossaryResource;
|
||||
import org.openmetadata.catalog.type.ChangeDescription;
|
||||
import org.openmetadata.catalog.type.EntityReference;
|
||||
import org.openmetadata.catalog.type.Relationship;
|
||||
import org.openmetadata.catalog.type.TagLabel;
|
||||
import org.openmetadata.catalog.util.EntityInterface;
|
||||
import org.openmetadata.catalog.util.EntityUtil;
|
||||
@ -37,8 +41,8 @@ import org.openmetadata.catalog.util.EntityUtil.Fields;
|
||||
import org.openmetadata.catalog.util.JsonUtils;
|
||||
|
||||
public class GlossaryRepository extends EntityRepository<Glossary> {
|
||||
private static final Fields GLOSSARY_UPDATE_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "owner,tags");
|
||||
private static final Fields GLOSSARY_PATCH_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "owner,tags");
|
||||
private static final Fields UPDATE_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "owner,tags,reviewers");
|
||||
private static final Fields PATCH_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "owner,tags,reviewers");
|
||||
|
||||
public GlossaryRepository(CollectionDAO dao) {
|
||||
super(
|
||||
@ -47,8 +51,8 @@ public class GlossaryRepository extends EntityRepository<Glossary> {
|
||||
Glossary.class,
|
||||
dao.glossaryDAO(),
|
||||
dao,
|
||||
GLOSSARY_PATCH_FIELDS,
|
||||
GLOSSARY_UPDATE_FIELDS,
|
||||
PATCH_FIELDS,
|
||||
UPDATE_FIELDS,
|
||||
true,
|
||||
true,
|
||||
false);
|
||||
@ -63,13 +67,14 @@ public class GlossaryRepository extends EntityRepository<Glossary> {
|
||||
public Glossary setFields(Glossary glossary, Fields fields) throws IOException, ParseException {
|
||||
glossary.setOwner(fields.contains(FIELD_OWNER) ? getOwner(glossary) : null);
|
||||
glossary.setTags(fields.contains("tags") ? getTags(glossary.getName()) : null);
|
||||
glossary.setReviewers(fields.contains("reviewers") ? getReviewers(glossary) : null);
|
||||
return glossary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare(Glossary glossary) throws IOException, ParseException {
|
||||
glossary.setOwner(helper(glossary).validateOwnerOrNull());
|
||||
// TODO validate reviewers
|
||||
validateUsers(glossary.getReviewers());
|
||||
glossary.setTags(EntityUtil.addDerivedTags(daoCollection.tagDAO(), glossary.getTags()));
|
||||
}
|
||||
|
||||
@ -78,7 +83,7 @@ public class GlossaryRepository extends EntityRepository<Glossary> {
|
||||
// Relationships and fields such as href are derived and not stored as part of json
|
||||
EntityReference owner = glossary.getOwner();
|
||||
List<TagLabel> tags = glossary.getTags();
|
||||
// TODO Add relationships for reviewers
|
||||
List<EntityReference> reviewers = glossary.getReviewers();
|
||||
|
||||
// Don't store owner, href and tags as JSON. Build it on the fly based on relationships
|
||||
glossary.withOwner(null).withHref(null).withTags(null);
|
||||
@ -90,14 +95,16 @@ public class GlossaryRepository extends EntityRepository<Glossary> {
|
||||
}
|
||||
|
||||
// Restore the relationships
|
||||
glossary.withOwner(owner).withTags(tags);
|
||||
glossary.withOwner(owner).withTags(tags).withReviewers(reviewers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeRelationships(Glossary glossary) {
|
||||
// TODO Add relationships for related terms, and reviewers
|
||||
setOwner(glossary, glossary.getOwner());
|
||||
applyTags(glossary);
|
||||
for (EntityReference reviewer : Optional.ofNullable(glossary.getReviewers()).orElse(Collections.emptyList())) {
|
||||
addRelationship(reviewer.getId(), glossary.getId(), Entity.USER, Entity.GLOSSARY, Relationship.REVIEWS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -110,6 +117,13 @@ public class GlossaryRepository extends EntityRepository<Glossary> {
|
||||
return new GlossaryUpdater(original, updated, operation);
|
||||
}
|
||||
|
||||
private List<EntityReference> getReviewers(Glossary entity) throws IOException {
|
||||
List<String> ids =
|
||||
findFrom(entity.getId(), Entity.GLOSSARY, Relationship.REVIEWS, Entity.USER, entity.getDeleted());
|
||||
System.out.println("XXX reviewers for " + entity.getId() + " " + ids);
|
||||
return EntityUtil.populateEntityReferences(ids, Entity.USER);
|
||||
}
|
||||
|
||||
public static class GlossaryEntityInterface implements EntityInterface<Glossary> {
|
||||
private final Glossary entity;
|
||||
|
||||
@ -260,5 +274,25 @@ public class GlossaryRepository extends EntityRepository<Glossary> {
|
||||
public GlossaryUpdater(Glossary original, Glossary updated, Operation operation) {
|
||||
super(original, updated, operation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entitySpecificUpdate() throws IOException, ParseException {
|
||||
updateReviewers(original.getEntity(), updated.getEntity());
|
||||
}
|
||||
|
||||
private void updateReviewers(Glossary origGlossary, Glossary updatedGlossary) throws JsonProcessingException {
|
||||
List<EntityReference> origUsers =
|
||||
Optional.ofNullable(origGlossary.getReviewers()).orElse(Collections.emptyList());
|
||||
List<EntityReference> updatedUsers =
|
||||
Optional.ofNullable(updatedGlossary.getReviewers()).orElse(Collections.emptyList());
|
||||
updateFromRelationships(
|
||||
"reviewers",
|
||||
Entity.USER,
|
||||
origUsers,
|
||||
updatedUsers,
|
||||
Relationship.REVIEWS,
|
||||
Entity.GLOSSARY,
|
||||
origGlossary.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,9 +16,13 @@
|
||||
|
||||
package org.openmetadata.catalog.jdbi3;
|
||||
|
||||
import static org.openmetadata.catalog.util.EntityUtil.stringMatch;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@ -39,8 +43,8 @@ import org.openmetadata.catalog.util.JsonUtils;
|
||||
|
||||
@Slf4j
|
||||
public class GlossaryTermRepository extends EntityRepository<GlossaryTerm> {
|
||||
private static final Fields UPDATE_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "tags");
|
||||
private static final Fields PATCH_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "tags");
|
||||
private static final Fields UPDATE_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "tags,reviewers");
|
||||
private static final Fields PATCH_FIELDS = new Fields(GlossaryResource.ALLOWED_FIELDS, "tags,reviewers");
|
||||
|
||||
public GlossaryTermRepository(CollectionDAO dao) {
|
||||
super(
|
||||
@ -166,11 +170,10 @@ public class GlossaryTermRepository extends EntityRepository<GlossaryTerm> {
|
||||
}
|
||||
for (EntityReference relTerm : Optional.ofNullable(entity.getRelatedTerms()).orElse(Collections.emptyList())) {
|
||||
// Make this bidirectional relationship
|
||||
addRelationship(
|
||||
addBidirectionalRelationship(
|
||||
entity.getId(), relTerm.getId(), Entity.GLOSSARY_TERM, Entity.GLOSSARY_TERM, Relationship.RELATED_TO);
|
||||
}
|
||||
for (EntityReference reviewer : Optional.ofNullable(entity.getReviewers()).orElse(Collections.emptyList())) {
|
||||
// Make this bidirectional relationship
|
||||
addRelationship(reviewer.getId(), entity.getId(), Entity.USER, Entity.GLOSSARY_TERM, Relationship.REVIEWS);
|
||||
}
|
||||
|
||||
@ -349,7 +352,31 @@ public class GlossaryTermRepository extends EntityRepository<GlossaryTerm> {
|
||||
|
||||
@Override
|
||||
public void entitySpecificUpdate() throws IOException {
|
||||
// TODO
|
||||
updateSynonyms(original.getEntity(), updated.getEntity());
|
||||
updateReviewers(original.getEntity(), updated.getEntity());
|
||||
}
|
||||
|
||||
private void updateSynonyms(GlossaryTerm origTerm, GlossaryTerm updatedTerm) throws JsonProcessingException {
|
||||
List<String> origSynonyms = Optional.ofNullable(origTerm.getSynonyms()).orElse(Collections.emptyList());
|
||||
List<String> updatedSynonyms = Optional.ofNullable(updatedTerm.getSynonyms()).orElse(Collections.emptyList());
|
||||
|
||||
List<String> added = new ArrayList<>();
|
||||
List<String> deleted = new ArrayList<>();
|
||||
recordListChange("synonyms", origSynonyms, updatedSynonyms, added, deleted, stringMatch);
|
||||
}
|
||||
|
||||
private void updateReviewers(GlossaryTerm origTerm, GlossaryTerm updatedTerm) throws JsonProcessingException {
|
||||
List<EntityReference> origUsers = Optional.ofNullable(origTerm.getReviewers()).orElse(Collections.emptyList());
|
||||
List<EntityReference> updatedUsers =
|
||||
Optional.ofNullable(updatedTerm.getReviewers()).orElse(Collections.emptyList());
|
||||
updateFromRelationships(
|
||||
"reviewers",
|
||||
Entity.USER,
|
||||
origUsers,
|
||||
updatedUsers,
|
||||
Relationship.REVIEWS,
|
||||
Entity.GLOSSARY_TERM,
|
||||
origTerm.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
|
||||
package org.openmetadata.catalog.jdbi3;
|
||||
|
||||
import static org.openmetadata.catalog.util.EntityUtil.entityReferenceMatch;
|
||||
import static org.openmetadata.catalog.util.EntityUtil.toBoolean;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
@ -63,26 +62,6 @@ public class TeamRepository extends EntityRepository<Team> {
|
||||
return entityReferences;
|
||||
}
|
||||
|
||||
public void validateEntityReferences(List<EntityReference> entityReferences, String entityType) throws IOException {
|
||||
if (entityReferences != null) {
|
||||
entityReferences.sort(EntityUtil.compareEntityReference);
|
||||
for (EntityReference entityReference : entityReferences) {
|
||||
EntityReference ref;
|
||||
switch (entityType) {
|
||||
case Entity.USER:
|
||||
ref = daoCollection.userDAO().findEntityReferenceById(entityReference.getId());
|
||||
break;
|
||||
case Entity.ROLE:
|
||||
ref = daoCollection.roleDAO().findEntityReferenceById(entityReference.getId());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported entity reference for validation");
|
||||
}
|
||||
entityReference.withType(ref.getType()).withName(ref.getName()).withDisplayName(ref.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Team setFields(Team team, Fields fields) throws IOException {
|
||||
if (!fields.contains("profile")) {
|
||||
@ -107,8 +86,8 @@ public class TeamRepository extends EntityRepository<Team> {
|
||||
|
||||
@Override
|
||||
public void prepare(Team team) throws IOException {
|
||||
validateEntityReferences(team.getUsers(), Entity.USER);
|
||||
validateEntityReferences(team.getDefaultRoles(), Entity.ROLE);
|
||||
validateUsers(team.getUsers());
|
||||
validateRoles(team.getDefaultRoles());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -297,8 +276,8 @@ public class TeamRepository extends EntityRepository<Team> {
|
||||
private void updateUsers(Team origTeam, Team updatedTeam) throws JsonProcessingException {
|
||||
List<EntityReference> origUsers = Optional.ofNullable(origTeam.getUsers()).orElse(Collections.emptyList());
|
||||
List<EntityReference> updatedUsers = Optional.ofNullable(updatedTeam.getUsers()).orElse(Collections.emptyList());
|
||||
updateEntityRelationships(
|
||||
"users", origTeam.getId(), updatedTeam.getId(), Relationship.HAS, Entity.USER, origUsers, updatedUsers);
|
||||
updateToRelationships(
|
||||
"users", Entity.TEAM, origTeam.getId(), Relationship.HAS, Entity.USER, origUsers, updatedUsers);
|
||||
}
|
||||
|
||||
private void updateDefaultRoles(Team origTeam, Team updatedTeam) throws JsonProcessingException {
|
||||
@ -306,41 +285,14 @@ public class TeamRepository extends EntityRepository<Team> {
|
||||
Optional.ofNullable(origTeam.getDefaultRoles()).orElse(Collections.emptyList());
|
||||
List<EntityReference> updatedDefaultRoles =
|
||||
Optional.ofNullable(updatedTeam.getDefaultRoles()).orElse(Collections.emptyList());
|
||||
updateEntityRelationships(
|
||||
updateToRelationships(
|
||||
"defaultRoles",
|
||||
Entity.TEAM,
|
||||
origTeam.getId(),
|
||||
updatedTeam.getId(),
|
||||
Relationship.HAS,
|
||||
Entity.ROLE,
|
||||
origDefaultRoles,
|
||||
updatedDefaultRoles);
|
||||
}
|
||||
|
||||
private void updateEntityRelationships(
|
||||
String field,
|
||||
UUID origId,
|
||||
UUID updatedId,
|
||||
Relationship relationshipType,
|
||||
String toEntityType,
|
||||
List<EntityReference> origRefs,
|
||||
List<EntityReference> updatedRefs)
|
||||
throws JsonProcessingException {
|
||||
List<EntityReference> added = new ArrayList<>();
|
||||
List<EntityReference> deleted = new ArrayList<>();
|
||||
if (!recordListChange(field, origRefs, updatedRefs, added, deleted, entityReferenceMatch)) {
|
||||
// No changes between original and updated.
|
||||
return;
|
||||
}
|
||||
// Remove relationships from original
|
||||
daoCollection
|
||||
.relationshipDAO()
|
||||
.deleteFrom(origId.toString(), Entity.TEAM, relationshipType.ordinal(), toEntityType);
|
||||
// Add relationships from updated
|
||||
for (EntityReference ref : updatedRefs) {
|
||||
addRelationship(updatedId, ref.getId(), Entity.TEAM, toEntityType, relationshipType);
|
||||
}
|
||||
updatedRefs.sort(EntityUtil.compareEntityReference);
|
||||
origRefs.sort(EntityUtil.compareEntityReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ public class UserRepository extends EntityRepository<User> {
|
||||
.findTo(user.getId().toString(), Entity.USER, Relationship.FOLLOWS.ordinal(), toBoolean(toInclude(user))));
|
||||
}
|
||||
|
||||
public List<EntityReference> validateRoles(List<UUID> roleIds) throws IOException {
|
||||
public List<EntityReference> validateRolesByIds(List<UUID> roleIds) throws IOException {
|
||||
if (roleIds == null) {
|
||||
return Collections.emptyList(); // Return an empty roles list
|
||||
}
|
||||
|
||||
@ -88,6 +88,7 @@ public class GlossaryResource {
|
||||
public static Glossary addHref(UriInfo uriInfo, Glossary glossary) {
|
||||
glossary.setHref(RestUtil.getHref(uriInfo, COLLECTION_PATH, glossary.getId()));
|
||||
Entity.withHref(uriInfo, glossary.getOwner());
|
||||
Entity.withHref(uriInfo, glossary.getReviewers());
|
||||
return glossary;
|
||||
}
|
||||
|
||||
@ -110,7 +111,7 @@ public class GlossaryResource {
|
||||
}
|
||||
}
|
||||
|
||||
static final String FIELDS = "owner,tags";
|
||||
static final String FIELDS = "owner,tags,reviewers";
|
||||
public static final List<String> ALLOWED_FIELDS = Entity.getEntityFields(Glossary.class);
|
||||
|
||||
@GET
|
||||
|
||||
@ -434,6 +434,6 @@ public class UserResource {
|
||||
.withUpdatedBy(securityContext.getUserPrincipal().getName())
|
||||
.withUpdatedAt(System.currentTimeMillis())
|
||||
.withTeams(dao.validateTeams(create.getTeams()))
|
||||
.withRoles(dao.validateRoles(create.getRoles()));
|
||||
.withRoles(dao.validateRolesByIds(create.getRoles()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,10 +18,10 @@
|
||||
"type": "string"
|
||||
},
|
||||
"reviewers": {
|
||||
"description": "User names of the reviewers for this glossary.",
|
||||
"description": "User references of the reviewers for this glossary.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"owner": {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"$id": "https://open-metadata.org/schema/entity/data/glossary.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Glossary",
|
||||
"description": "This schema defines the Glossary entity based on SKOS.",
|
||||
"description": "This schema defines the Glossary entity. A Glossary is collection of hierarchical GlossaryTerms.",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"name": {
|
||||
@ -47,10 +47,10 @@
|
||||
"$ref": "../../type/basic.json#/definitions/href"
|
||||
},
|
||||
"reviewers": {
|
||||
"description": "User names of the reviewers for this glossary.",
|
||||
"description": "User references of the reviewers for this glossary.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"owner": {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"$id": "https://open-metadata.org/schema/entity/data/glossaryTerm.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "GlossaryTerm",
|
||||
"description": "This schema defines the Glossary term entities.",
|
||||
"description": "This schema defines te Glossary term entities.",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"name": {
|
||||
@ -94,10 +94,6 @@
|
||||
"description": "User who made the update.",
|
||||
"type": "string"
|
||||
},
|
||||
"skos": {
|
||||
"description": "SKOS data in JSON-LD format",
|
||||
"type": "string"
|
||||
},
|
||||
"href": {
|
||||
"description": "Link to the resource corresponding to this entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/href"
|
||||
|
||||
@ -1952,7 +1952,14 @@ public abstract class EntityResourceTest<T, K> extends CatalogApplicationTest {
|
||||
for (EntityReference expected : expectedList) {
|
||||
EntityReference actual =
|
||||
actualList.stream().filter(a -> EntityUtil.entityReferenceMatch.test(a, expected)).findAny().orElse(null);
|
||||
assertNotNull(actual, "Expected entity " + expected.getId() + " not found");
|
||||
assertNotNull(actual, "Expected entity reference " + expected.getId() + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertStrings(List<String> expectedList, List<String> actualList) {
|
||||
for (String expected : expectedList) {
|
||||
String actual = actualList.stream().filter(a -> EntityUtil.stringMatch.test(a, expected)).findAny().orElse(null);
|
||||
assertNotNull(actual, "Expected string " + expected + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,10 +22,12 @@ import static org.openmetadata.catalog.util.TestUtils.assertListNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.http.client.HttpResponseException;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.openmetadata.catalog.Entity;
|
||||
@ -33,8 +35,12 @@ import org.openmetadata.catalog.api.data.CreateGlossary;
|
||||
import org.openmetadata.catalog.entity.data.Glossary;
|
||||
import org.openmetadata.catalog.jdbi3.GlossaryRepository.GlossaryEntityInterface;
|
||||
import org.openmetadata.catalog.resources.EntityResourceTest;
|
||||
import org.openmetadata.catalog.type.ChangeDescription;
|
||||
import org.openmetadata.catalog.type.EntityReference;
|
||||
import org.openmetadata.catalog.type.FieldChange;
|
||||
import org.openmetadata.catalog.util.JsonUtils;
|
||||
import org.openmetadata.catalog.util.TestUtils;
|
||||
import org.openmetadata.catalog.util.TestUtils.UpdateType;
|
||||
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlossary> {
|
||||
@ -57,6 +63,26 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
||||
super.setup(test);
|
||||
}
|
||||
|
||||
@Test
|
||||
void patch_addDeleteReviewers(TestInfo test) throws IOException {
|
||||
CreateGlossary create = createRequest(getEntityName(test), "", "", null);
|
||||
Glossary glossary = createEntity(create, ADMIN_AUTH_HEADERS);
|
||||
|
||||
// Add reviewer USER1 in PATCH request
|
||||
String origJson = JsonUtils.pojoToJson(glossary);
|
||||
glossary.withReviewers(List.of(USER_OWNER1));
|
||||
ChangeDescription change = getChangeDescription(glossary.getVersion());
|
||||
change.getFieldsAdded().add(new FieldChange().withName("reviewers").withNewValue(List.of(USER_OWNER1)));
|
||||
glossary = patchEntityAndCheck(glossary, origJson, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
|
||||
|
||||
// Remove a reviewer in PATCH request
|
||||
origJson = JsonUtils.pojoToJson(glossary);
|
||||
glossary.withReviewers(null);
|
||||
change = getChangeDescription(glossary.getVersion());
|
||||
change.getFieldsDeleted().add(new FieldChange().withName("reviewers").withOldValue(List.of(USER_OWNER1)));
|
||||
patchEntityAndCheck(glossary, origJson, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateGlossary createRequest(String name, String description, String displayName, EntityReference owner) {
|
||||
return new CreateGlossary()
|
||||
@ -91,6 +117,7 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
||||
|
||||
// Entity specific validation
|
||||
TestUtils.validateTags(expected.getTags(), patched.getTags());
|
||||
TestUtils.assertEntityReferenceList(expected.getReviewers(), patched.getReviewers());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -120,6 +147,13 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
||||
if (expected == actual) {
|
||||
return;
|
||||
}
|
||||
assertCommonFieldChange(fieldName, expected, actual);
|
||||
if (fieldName.equals("reviewers")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<EntityReference> expectedRefs = (List<EntityReference>) expected;
|
||||
List<EntityReference> actualRefs = JsonUtils.readObjects(actual.toString(), EntityReference.class);
|
||||
assertEntityReferencesFieldChange(expectedRefs, actualRefs);
|
||||
} else {
|
||||
assertCommonFieldChange(fieldName, expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,10 +50,14 @@ import org.openmetadata.catalog.entity.data.GlossaryTerm;
|
||||
import org.openmetadata.catalog.jdbi3.GlossaryRepository.GlossaryEntityInterface;
|
||||
import org.openmetadata.catalog.jdbi3.GlossaryTermRepository.GlossaryTermEntityInterface;
|
||||
import org.openmetadata.catalog.resources.EntityResourceTest;
|
||||
import org.openmetadata.catalog.type.ChangeDescription;
|
||||
import org.openmetadata.catalog.type.EntityReference;
|
||||
import org.openmetadata.catalog.type.FieldChange;
|
||||
import org.openmetadata.catalog.util.EntityUtil;
|
||||
import org.openmetadata.catalog.util.JsonUtils;
|
||||
import org.openmetadata.catalog.util.ResultList;
|
||||
import org.openmetadata.catalog.util.TestUtils;
|
||||
import org.openmetadata.catalog.util.TestUtils.UpdateType;
|
||||
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, CreateGlossaryTerm> {
|
||||
@ -178,6 +182,28 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
|
||||
glossaryTermMismatch(term1.getId().toString(), glossary2.getId().toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void patch_addDeleteReviewers(TestInfo test) throws IOException {
|
||||
CreateGlossaryTerm create = createRequest(getEntityName(test), "", "", null).withReviewers(null).withSynonyms(null);
|
||||
GlossaryTerm term = createEntity(create, ADMIN_AUTH_HEADERS);
|
||||
|
||||
// Add reviewer USER1 in PATCH request
|
||||
String origJson = JsonUtils.pojoToJson(term);
|
||||
term.withReviewers(List.of(USER_OWNER1)).withSynonyms(List.of("synonym1"));
|
||||
ChangeDescription change = getChangeDescription(term.getVersion());
|
||||
change.getFieldsAdded().add(new FieldChange().withName("reviewers").withNewValue(List.of(USER_OWNER1)));
|
||||
change.getFieldsAdded().add(new FieldChange().withName("synonyms").withNewValue(List.of("synonym1")));
|
||||
term = patchEntityAndCheck(term, origJson, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
|
||||
|
||||
// Remove a reviewer in PATCH request
|
||||
origJson = JsonUtils.pojoToJson(term);
|
||||
term.withReviewers(null).withSynonyms(null);
|
||||
change = getChangeDescription(term.getVersion());
|
||||
change.getFieldsDeleted().add(new FieldChange().withName("reviewers").withOldValue(List.of(USER_OWNER1)));
|
||||
change.getFieldsDeleted().add(new FieldChange().withName("synonyms").withOldValue(List.of("synonym1")));
|
||||
patchEntityAndCheck(term, origJson, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
|
||||
}
|
||||
|
||||
public GlossaryTerm createTerm(Glossary glossary, GlossaryTerm parent, String termName) throws HttpResponseException {
|
||||
EntityReference glossaryRef = new GlossaryEntityInterface(glossary).getEntityReference();
|
||||
EntityReference parentRef = parent != null ? new GlossaryTermEntityInterface(parent).getEntityReference() : null;
|
||||
@ -281,6 +307,18 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
|
||||
if (expected == actual) {
|
||||
return;
|
||||
}
|
||||
assertCommonFieldChange(fieldName, expected, actual);
|
||||
if (fieldName.equals("reviewers")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<EntityReference> expectedRefs = (List<EntityReference>) expected;
|
||||
List<EntityReference> actualRefs = JsonUtils.readObjects(actual.toString(), EntityReference.class);
|
||||
assertEntityReferencesFieldChange(expectedRefs, actualRefs);
|
||||
} else if (fieldName.equals("synonyms")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> expectedRefs = (List<String>) expected;
|
||||
List<String> actualRefs = JsonUtils.readObjects(actual.toString(), String.class);
|
||||
assertStrings(expectedRefs, actualRefs);
|
||||
} else {
|
||||
assertCommonFieldChange(fieldName, expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user