334 lines
13 KiB
Java
Raw Normal View History

2021-08-01 14:27:44 -07:00
/*
* Copyright 2021 Collate
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
2021-08-01 14:27:44 -07:00
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openmetadata.service;
2021-08-01 14:27:44 -07:00
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
2021-11-09 13:25:08 -08:00
import java.io.IOException;
import java.net.URI;
2022-03-20 18:01:51 -07:00
import java.util.ArrayList;
import java.util.Arrays;
2021-11-09 13:25:08 -08:00
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import javax.ws.rs.core.UriInfo;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.openmetadata.schema.EntityInterface;
import org.openmetadata.schema.type.EntityReference;
import org.openmetadata.schema.type.Include;
import org.openmetadata.service.exception.CatalogExceptionMessage;
import org.openmetadata.service.exception.EntityNotFoundException;
import org.openmetadata.service.jdbi3.EntityDAO;
import org.openmetadata.service.jdbi3.EntityRepository;
import org.openmetadata.service.util.EntityUtil;
import org.openmetadata.service.util.EntityUtil.Fields;
2021-11-09 13:25:08 -08:00
@Slf4j
2021-08-01 14:27:44 -07:00
public final class Entity {
// Fully qualified name separator
public static final String SEPARATOR = ".";
// Canonical entity name to corresponding EntityDAO map
2021-11-10 16:07:06 -08:00
private static final Map<String, EntityDAO<?>> DAO_MAP = new HashMap<>();
// Canonical entity name to corresponding EntityRepository map
private static final Map<String, EntityRepository<?>> ENTITY_REPOSITORY_MAP = new HashMap<>();
// List of all the entities
private static final List<String> ENTITY_LIST = new ArrayList<>();
// Common field names
public static final String FIELD_OWNER = "owner";
2022-04-22 18:57:08 -07:00
public static final String FIELD_NAME = "name";
public static final String FIELD_DESCRIPTION = "description";
public static final String FIELD_FOLLOWERS = "followers";
public static final String FIELD_TAGS = "tags";
public static final String FIELD_DELETED = "deleted";
public static final String FIELD_PIPELINE_STATUS = "pipelineStatus";
2022-04-22 18:57:08 -07:00
public static final String FIELD_DISPLAY_NAME = "displayName";
public static final String FIELD_EXTENSION = "extension";
public static final String FIELD_USAGE_SUMMARY = "usageSummary";
2021-11-09 13:25:08 -08:00
//
// Service entities
2021-11-09 13:25:08 -08:00
//
2021-08-01 14:27:44 -07:00
public static final String DATABASE_SERVICE = "databaseService";
public static final String MESSAGING_SERVICE = "messagingService";
public static final String DASHBOARD_SERVICE = "dashboardService";
2021-09-24 08:54:04 -07:00
public static final String PIPELINE_SERVICE = "pipelineService";
public static final String STORAGE_SERVICE = "storageService";
public static final String MLMODEL_SERVICE = "mlmodelService";
public static final String METADATA_SERVICE = "metadataService";
2021-08-01 14:27:44 -07:00
2021-11-09 13:25:08 -08:00
//
// Data asset entities
2021-11-09 13:25:08 -08:00
//
2021-08-01 14:27:44 -07:00
public static final String TABLE = "table";
public static final String DATABASE = "database";
public static final String DATABASE_SCHEMA = "databaseSchema";
2021-08-01 14:27:44 -07:00
public static final String METRICS = "metrics";
public static final String DASHBOARD = "dashboard";
2021-09-24 08:54:04 -07:00
public static final String PIPELINE = "pipeline";
public static final String CHART = "chart";
2021-08-01 14:27:44 -07:00
public static final String REPORT = "report";
public static final String TOPIC = "topic";
public static final String MLMODEL = "mlmodel";
public static final String BOT = "bot";
public static final String ALERT = "alert";
public static final String THREAD = "THREAD";
public static final String LOCATION = "location";
public static final String GLOSSARY = "glossary";
public static final String GLOSSARY_TERM = "glossaryTerm";
public static final String TAG = "tag";
public static final String CLASSIFICATION = "classification";
public static final String TYPE = "type";
public static final String TEST_DEFINITION = "testDefinition";
public static final String ALERT_ACTION = "alertAction";
public static final String TEST_SUITE = "testSuite";
public static final String KPI = "kpi";
public static final String TEST_CASE = "testCase";
public static final String WEB_ANALYTIC_EVENT = "webAnalyticEvent";
public static final String DATA_INSIGHT_CHART = "dataInsightChart";
2021-08-01 14:27:44 -07:00
2021-11-09 13:25:08 -08:00
//
// Policy entity
2021-11-09 13:25:08 -08:00
//
public static final String POLICY = "policy";
public static final String POLICIES = "policies";
2021-11-09 13:25:08 -08:00
//
// Role, team and user entities
2021-11-09 13:25:08 -08:00
//
2021-12-30 08:30:12 -08:00
public static final String ROLE = "role";
2021-08-01 14:27:44 -07:00
public static final String USER = "user";
public static final String TEAM = "team";
//
// Operation related entities
//
public static final String INGESTION_PIPELINE = "ingestionPipeline";
public static final String WEBHOOK = "webhook";
//
// Reserved names in OpenMetadata
//
public static final String ADMIN_USER_NAME = "admin";
public static final String ORGANIZATION_NAME = "Organization";
public static final String ORGANIZATION_POLICY_NAME = "OrganizationPolicy";
public static final String INGESTION_BOT_NAME = "ingestion-bot";
public static final String INGESTION_BOT_ROLE = "IngestionBotRole";
public static final String PROFILER_BOT_NAME = "profiler-bot";
public static final String PROFILER_BOT_ROLE = "ProfilerBotRole";
public static final String QUALITY_BOT_NAME = "quality-bot";
public static final String QUALITY_BOT_ROLE = "QualityBotRole";
//
// List of entities whose changes should not be published to the Activity Feed
//
public static final List<String> ACTIVITY_FEED_EXCLUDED_ENTITIES =
List.of(
USER,
TEAM,
ROLE,
POLICY,
BOT,
INGESTION_PIPELINE,
DATABASE_SERVICE,
PIPELINE_SERVICE,
DASHBOARD_SERVICE,
STORAGE_SERVICE,
MESSAGING_SERVICE);
private Entity() {}
2021-11-09 13:25:08 -08:00
public static <T extends EntityInterface> void registerEntity(
Class<T> clazz, String entity, EntityDAO<T> dao, EntityRepository<T> entityRepository) {
DAO_MAP.put(entity, dao);
2021-11-10 16:07:06 -08:00
ENTITY_REPOSITORY_MAP.put(entity, entityRepository);
EntityInterface.CANONICAL_ENTITY_NAME_MAP.put(entity.toLowerCase(Locale.ROOT), entity);
EntityInterface.ENTITY_TYPE_TO_CLASS_MAP.put(entity.toLowerCase(Locale.ROOT), clazz);
ENTITY_LIST.add(entity);
Collections.sort(ENTITY_LIST);
LOG.info("Registering entity {} {}", clazz, entity);
2021-11-09 13:25:08 -08:00
}
public static List<String> getEntityList() {
return Collections.unmodifiableList(ENTITY_LIST);
}
public static EntityReference getEntityReference(EntityReference ref) throws IOException {
return ref == null ? null : getEntityReferenceById(ref.getType(), ref.getId(), Include.NON_DELETED);
}
public static EntityReference getEntityReferenceByName(EntityReference ref) {
return ref == null
? null
: getEntityReferenceByName(ref.getType(), ref.getFullyQualifiedName(), Include.NON_DELETED);
}
public static EntityReference getEntityReferenceById(@NonNull String entityType, @NonNull UUID id, Include include)
throws IOException {
EntityRepository<?> repository = ENTITY_REPOSITORY_MAP.get(entityType);
if (repository == null) {
throw EntityNotFoundException.byMessage(CatalogExceptionMessage.entityTypeNotFound(entityType));
}
include = repository.supportsSoftDelete ? Include.ALL : include;
return repository.dao.findEntityReferenceById(id, include);
}
public static EntityReference getEntityReferenceByName(@NonNull String entityType, String fqn, Include include) {
if (fqn == null) {
return null;
}
EntityDAO<?> dao = DAO_MAP.get(entityType);
if (dao == null) {
throw EntityNotFoundException.byMessage(CatalogExceptionMessage.entityTypeNotFound(entityType));
2021-11-09 13:25:08 -08:00
}
return dao.findEntityReferenceByName(fqn, include);
}
public static EntityReference getOwner(@NonNull EntityReference reference) throws IOException {
EntityRepository<?> repository = getEntityRepository(reference.getType());
return repository.getOwner(reference);
2021-11-09 13:25:08 -08:00
}
public static void withHref(UriInfo uriInfo, List<EntityReference> list) {
listOrEmpty(list).forEach(ref -> withHref(uriInfo, ref));
2021-11-09 13:25:08 -08:00
}
public static void withHref(UriInfo uriInfo, EntityReference ref) {
2021-11-09 13:25:08 -08:00
if (ref == null) {
return;
2021-11-09 13:25:08 -08:00
}
String entityType = ref.getType();
EntityRepository<?> entityRepository = getEntityRepository(entityType);
2021-11-09 13:25:08 -08:00
URI href = entityRepository.getHref(uriInfo, ref.getId());
ref.withHref(href);
2021-11-09 13:25:08 -08:00
}
2021-08-01 14:27:44 -07:00
/** Returns true if the change events of the given entity type should be published to the activity feed. */
public static boolean shouldDisplayEntityChangeOnFeed(@NonNull String entityType) {
return !ACTIVITY_FEED_EXCLUDED_ENTITIES.contains(entityType);
}
public static Fields getFields(String entityType, String fields) {
EntityRepository<?> entityRepository = Entity.getEntityRepository(entityType);
return entityRepository.getFields(fields);
}
public static <T> T getEntity(EntityReference ref, String fields, Include include) throws IOException {
return getEntity(ref.getType(), ref.getId(), fields, include);
}
public static <T> T getEntity(EntityReference ref, EntityUtil.Fields fields, Include include) throws IOException {
2022-03-20 18:01:51 -07:00
return getEntity(ref.getType(), ref.getId(), fields, include);
}
public static <T> T getEntity(String entityType, UUID id, String fields, Include include) throws IOException {
return getEntity(entityType, id, getFields(entityType, fields), include);
}
2022-03-20 18:01:51 -07:00
/** Retrieve the entity using id from given entity reference and fields */
public static <T> T getEntity(String entityType, UUID id, EntityUtil.Fields fields, Include include)
throws IOException {
2022-03-20 18:01:51 -07:00
EntityRepository<?> entityRepository = Entity.getEntityRepository(entityType);
@SuppressWarnings("unchecked")
T entity = (T) entityRepository.get(null, id, fields, include);
if (entity == null) {
2022-03-20 18:01:51 -07:00
throw EntityNotFoundException.byMessage(CatalogExceptionMessage.entityNotFound(entityType, id));
}
return entity;
}
/** Retrieve the corresponding entity repository for a given entity name. */
public static <T extends EntityInterface> EntityRepository<T> getEntityRepository(@NonNull String entityType) {
@SuppressWarnings("unchecked")
EntityRepository<T> entityRepository = (EntityRepository<T>) ENTITY_REPOSITORY_MAP.get(entityType);
2021-11-09 13:25:08 -08:00
if (entityRepository == null) {
throw EntityNotFoundException.byMessage(CatalogExceptionMessage.entityTypeNotFound(entityType));
2021-11-09 13:25:08 -08:00
}
return entityRepository;
2021-08-01 14:27:44 -07:00
}
2022-03-20 18:01:51 -07:00
public static void deleteEntity(
String updatedBy, String entityType, UUID entityId, boolean recursive, boolean hardDelete) throws IOException {
EntityRepository<?> dao = getEntityRepository(entityType);
dao.delete(updatedBy, entityId, recursive, hardDelete);
}
public static void restoreEntity(String updatedBy, String entityType, UUID entityId) throws IOException {
EntityRepository<?> dao = getEntityRepository(entityType);
dao.restoreEntity(updatedBy, entityType, entityId);
}
public static <T> String getEntityTypeFromClass(Class<T> clz) {
return EntityInterface.CANONICAL_ENTITY_NAME_MAP.get(clz.getSimpleName().toLowerCase(Locale.ROOT));
}
public static String getEntityTypeFromObject(Object object) {
return EntityInterface.CANONICAL_ENTITY_NAME_MAP.get(object.getClass().getSimpleName().toLowerCase(Locale.ROOT));
}
public static Class<? extends EntityInterface> getEntityClassFromType(String entityType) {
return EntityInterface.ENTITY_TYPE_TO_CLASS_MAP.get(entityType);
}
/**
* Get list of all the entity field names from JsonPropertyOrder annotation from generated java class from entity.json
*/
public static <T> List<String> getEntityFields(Class<T> clz) {
JsonPropertyOrder propertyOrder = clz.getAnnotation(JsonPropertyOrder.class);
2022-03-20 18:01:51 -07:00
return new ArrayList<>(Arrays.asList(propertyOrder.value()));
}
2022-05-05 22:56:26 -07:00
public static <T> List<String> getAllowedFields(Class<T> clz) {
String entityType = getEntityTypeFromClass(clz);
EntityRepository<?> repository = getEntityRepository(entityType);
return repository.getAllowedFields();
}
/** Class for getting validated entity list from a queryParam with list of entities. */
public static class EntityList {
private EntityList() {}
public static List<String> getEntityList(String name, String entitiesParam) {
if (entitiesParam == null) {
return Collections.emptyList();
}
entitiesParam = entitiesParam.replace(" ", "");
if (entitiesParam.equals("*")) {
return List.of("*");
}
List<String> list = Arrays.asList(entitiesParam.split(","));
validateEntities(name, list);
return list;
}
private static void validateEntities(String name, List<String> list) {
for (String entity : list) {
if (ENTITY_REPOSITORY_MAP.get(entity) == null) {
throw new IllegalArgumentException(String.format("Invalid entity %s in query param %s", entity, name));
}
}
}
}
2021-08-01 14:27:44 -07:00
}