Commit 95083cb0 by Sarath Subramanian Committed by Madhan Neethiraj

ATLAS-1242: update TypesResource API implementation to use new v2 TypesREST API

parent 710c17f5
...@@ -54,6 +54,7 @@ public enum AtlasErrorCode { ...@@ -54,6 +54,7 @@ public enum AtlasErrorCode {
TYPE_ALREADY_EXISTS(409, "ATLAS4091E", "Given type {0} already exists"), TYPE_ALREADY_EXISTS(409, "ATLAS4091E", "Given type {0} already exists"),
TYPE_HAS_REFERENCES(409, "ATLAS4092E", "Given type {0} has references"), TYPE_HAS_REFERENCES(409, "ATLAS4092E", "Given type {0} has references"),
TYPE_MATCH_FAILED(409, "ATLAS4093E", "Given type {0} doesn't match {1}"), TYPE_MATCH_FAILED(409, "ATLAS4093E", "Given type {0} doesn't match {1}"),
INVALID_TYPE_DEFINITION(409, "ATLAS4094E", "Invalid type definition {0}"),
INTERNAL_ERROR(500, "ATLAS5001E", "Internal server error {0}"), INTERNAL_ERROR(500, "ATLAS5001E", "Internal server error {0}"),
INDEX_CREATION_FAILED(500, "ATLAS5002E", "Index creation failed for {0}"), INDEX_CREATION_FAILED(500, "ATLAS5002E", "Index creation failed for {0}"),
......
...@@ -41,7 +41,7 @@ import javax.xml.bind.annotation.XmlRootElement; ...@@ -41,7 +41,7 @@ import javax.xml.bind.annotation.XmlRootElement;
public class SearchFilter { public class SearchFilter {
public static final String PARAM_TYPE = "type"; public static final String PARAM_TYPE = "type";
public static final String PARAM_SUPERTYPE = "supertype"; public static final String PARAM_SUPERTYPE = "supertype";
public static final String PARAM_NOT_SUPERTYPE = "notSupertype"; public static final String PARAM_NOT_SUPERTYPE = "notsupertype";
/** /**
* to specify whether the result should be sorted? If yes, whether asc or desc. * to specify whether the result should be sorted? If yes, whether asc or desc.
......
...@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al ...@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai) ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
ALL CHANGES: ALL CHANGES:
ATLAS-1242 update TypesResource API implementation to use new v2 TypesREST API
ATLAS-1306 bootstrap type-load ignores model file contents if a type in the file already exists ATLAS-1306 bootstrap type-load ignores model file contents if a type in the file already exists
ATLAS-1299 The project org.apache.atlas:atlas-hbase-client-shaded - build error (shwethags) ATLAS-1299 The project org.apache.atlas:atlas-hbase-client-shaded - build error (shwethags)
ATLAS-1246 Upgrade versions of dependencies (shwethags) ATLAS-1246 Upgrade versions of dependencies (shwethags)
......
...@@ -82,7 +82,7 @@ public class TypesUtil { ...@@ -82,7 +82,7 @@ public class TypesUtil {
public static HierarchicalTypeDefinition<TraitType> createTraitTypeDef(String name, String description, String version, public static HierarchicalTypeDefinition<TraitType> createTraitTypeDef(String name, String description, String version,
ImmutableSet<String> superTypes, AttributeDefinition... attrDefs) { ImmutableSet<String> superTypes, AttributeDefinition... attrDefs) {
return new HierarchicalTypeDefinition<>(TraitType.class, name, description, superTypes, attrDefs); return new HierarchicalTypeDefinition<>(TraitType.class, name, description, version, superTypes, attrDefs);
} }
public static StructTypeDefinition createStructTypeDef(String name, AttributeDefinition... attrDefs) { public static StructTypeDefinition createStructTypeDef(String name, AttributeDefinition... attrDefs) {
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.apache.atlas.util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.TypeCategory;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.typedef.AtlasClassificationDef;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasEnumDef;
import org.apache.atlas.model.typedef.AtlasEnumDef.AtlasEnumElementDef;
import org.apache.atlas.model.typedef.AtlasStructDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
import org.apache.atlas.model.typedef.AtlasTypeDefHeader;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.type.AtlasArrayType;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.type.AtlasTypeUtil;
import org.apache.atlas.typesystem.TypesDef;
import org.apache.atlas.typesystem.json.TypesSerialization;
import org.apache.atlas.typesystem.types.AttributeDefinition;
import org.apache.atlas.typesystem.types.ClassType;
import org.apache.atlas.typesystem.types.EnumTypeDefinition;
import org.apache.atlas.typesystem.types.EnumValue;
import org.apache.atlas.typesystem.types.HierarchicalTypeDefinition;
import org.apache.atlas.typesystem.types.Multiplicity;
import org.apache.atlas.typesystem.types.StructTypeDefinition;
import org.apache.atlas.typesystem.types.TraitType;
import org.apache.atlas.typesystem.types.utils.TypesUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.atlas.AtlasErrorCode.INVALID_TYPE_DEFINITION;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_MAPPED_FROM_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_VAL_CASCADE;
import static org.apache.atlas.type.AtlasTypeUtil.isArrayType;
public final class RestUtils {
private RestUtils() {}
private static final Logger LOG = LoggerFactory.getLogger(RestUtils.class);
public static TypesDef toTypesDef(AtlasEnumDef enumDef) {
TypesDef ret = null;
if (enumDef != null) {
String enumName = enumDef.getName();
String enumDesc = enumDef.getDescription();
String enumVersion = enumDef.getTypeVersion();
EnumValue[] enumValues = getEnumValues(enumDef.getElementDefs());
if (enumName != null && enumValues != null && enumValues.length > 0) {
EnumTypeDefinition enumTypeDef = new EnumTypeDefinition(enumName, enumDesc, enumVersion, enumValues);
ret = TypesUtil.getTypesDef(ImmutableList.of(enumTypeDef),
ImmutableList.<StructTypeDefinition>of(),
ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(),
ImmutableList.<HierarchicalTypeDefinition<ClassType>>of());
}
}
return ret;
}
public static TypesDef toTypesDef(AtlasStructDef structDef, AtlasTypeRegistry registry) throws AtlasBaseException {
String typeName = structDef.getName();
String typeDesc = structDef.getDescription();
AttributeDefinition[] attributes = getAttributes(structDef, registry);
StructTypeDefinition structType = TypesUtil.createStructTypeDef(typeName, typeDesc, attributes);
TypesDef ret = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(),
ImmutableList.of(structType),
ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(),
ImmutableList.<HierarchicalTypeDefinition<ClassType>>of());
return ret;
}
public static TypesDef toTypesDef(AtlasEntityDef entityDef, AtlasTypeRegistry registry) throws AtlasBaseException {
String typeName = entityDef.getName();
String typeDesc = entityDef.getDescription();
String typeVersion = entityDef.getTypeVersion();
ImmutableSet superTypes = ImmutableSet.copyOf(entityDef.getSuperTypes());
AttributeDefinition[] attributes = getAttributes(entityDef, registry);
HierarchicalTypeDefinition<ClassType> classType = TypesUtil.createClassTypeDef(typeName, typeDesc, typeVersion,
superTypes, attributes);
TypesDef ret = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(),
ImmutableList.<StructTypeDefinition>of(),
ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(),
ImmutableList.of(classType));
return ret;
}
public static TypesDef toTypesDef(AtlasClassificationDef classifDef, AtlasTypeRegistry registry) throws AtlasBaseException {
String typeName = classifDef.getName();
String typeDesc = classifDef.getDescription();
String typeVersion = classifDef.getTypeVersion();
ImmutableSet superTypes = ImmutableSet.copyOf(classifDef.getSuperTypes());
AttributeDefinition[] attributes = getAttributes(classifDef, registry);
HierarchicalTypeDefinition traitType = TypesUtil.createTraitTypeDef(typeName, typeDesc, typeVersion, superTypes,
attributes);
TypesDef ret = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(),
ImmutableList.<StructTypeDefinition>of(),
ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(traitType),
ImmutableList.<HierarchicalTypeDefinition<ClassType>>of());
return ret;
}
public static AtlasTypesDef toAtlasTypesDef(String typeDefinition, AtlasTypeRegistry registry) throws AtlasBaseException {
AtlasTypesDef ret = new AtlasTypesDef();
try {
if (StringUtils.isEmpty(typeDefinition)) {
throw new AtlasBaseException(INVALID_TYPE_DEFINITION, typeDefinition);
}
TypesDef typesDef = TypesSerialization.fromJson(typeDefinition);
if (CollectionUtils.isNotEmpty(typesDef.enumTypesAsJavaList())) {
List<AtlasEnumDef> enumDefs = toAtlasEnumDefs(typesDef.enumTypesAsJavaList());
ret.setEnumDefs(enumDefs);
}
if (CollectionUtils.isNotEmpty(typesDef.structTypesAsJavaList())) {
List<AtlasStructDef> structDefs = toAtlasStructDefs(typesDef.structTypesAsJavaList());
ret.setStructDefs(structDefs);
}
if (CollectionUtils.isNotEmpty(typesDef.classTypesAsJavaList())) {
List<AtlasEntityDef> entityDefs = toAtlasEntityDefs(typesDef.classTypesAsJavaList(), registry);
ret.setEntityDefs(entityDefs);
}
if (CollectionUtils.isNotEmpty(typesDef.traitTypesAsJavaList())) {
List<AtlasClassificationDef> classificationDefs = toAtlasClassificationDefs(typesDef.traitTypesAsJavaList());
ret.setClassificationDefs(classificationDefs);
}
} catch (Exception e) {
LOG.error("Invalid type definition = {}", typeDefinition, e);
throw new AtlasBaseException(INVALID_TYPE_DEFINITION, typeDefinition);
}
return ret;
}
public static ImmutableList<String> getTypeNames(List<AtlasTypeDefHeader> atlasTypesDefs) {
List<String> ret = new ArrayList<String>();
if (CollectionUtils.isNotEmpty(atlasTypesDefs)) {
for (AtlasTypeDefHeader atlasTypesDef : atlasTypesDefs) {
ret.add(atlasTypesDef.getName());
}
}
return ImmutableList.copyOf(ret);
}
public static List<String> getTypeNames(AtlasTypesDef typesDef) {
List<AtlasTypeDefHeader> atlasTypesDefs = AtlasTypeUtil.toTypeDefHeader(typesDef);
return getTypeNames(atlasTypesDefs);
}
private static List<AtlasEnumDef> toAtlasEnumDefs(List<EnumTypeDefinition> enumTypeDefinitions) {
List<AtlasEnumDef> ret = new ArrayList<AtlasEnumDef>();
for (EnumTypeDefinition enumType : enumTypeDefinitions) {
AtlasEnumDef enumDef = new AtlasEnumDef();
enumDef.setName(enumType.name);
enumDef.setDescription(enumType.description);
enumDef.setTypeVersion(enumType.version);
enumDef.setElementDefs(getAtlasEnumElementDefs(enumType.enumValues));
ret.add(enumDef);
}
return ret;
}
private static List<AtlasStructDef> toAtlasStructDefs(List<StructTypeDefinition> structTypeDefinitions)
throws AtlasBaseException {
List<AtlasStructDef> ret = new ArrayList<AtlasStructDef>();
for (StructTypeDefinition structType : structTypeDefinitions) {
AtlasStructDef structDef = new AtlasStructDef();
List<AtlasAttributeDef> attrDefs = new ArrayList<AtlasAttributeDef>();
structDef.setName(structType.typeName);
structDef.setDescription(structType.typeDescription);
structDef.setTypeVersion(structType.typeVersion);
AttributeDefinition[] attrDefinitions = structType.attributeDefinitions;
for (AttributeDefinition attrDefinition : attrDefinitions) {
attrDefs.add(toAtlasAttributeDef(attrDefinition));
}
structDef.setAttributeDefs(attrDefs);
ret.add(structDef);
}
return ret;
}
private static List<AtlasClassificationDef> toAtlasClassificationDefs(List<HierarchicalTypeDefinition<TraitType>> traitTypeDefinitions)
throws AtlasBaseException {
List<AtlasClassificationDef> ret = new ArrayList<AtlasClassificationDef>();
for (HierarchicalTypeDefinition<TraitType> traitType : traitTypeDefinitions) {
AtlasClassificationDef classifDef = new AtlasClassificationDef();
List<AtlasAttributeDef> attrDefs = new ArrayList<AtlasAttributeDef>();
classifDef.setName(traitType.typeName);
classifDef.setDescription(traitType.typeDescription);
classifDef.setTypeVersion(traitType.typeVersion);
classifDef.setSuperTypes(traitType.superTypes);
AttributeDefinition[] attrDefinitions = traitType.attributeDefinitions;
for (AttributeDefinition attrDefinition : attrDefinitions) {
attrDefs.add(toAtlasAttributeDef(attrDefinition));
}
classifDef.setAttributeDefs(attrDefs);
ret.add(classifDef);
}
return ret;
}
private static List<AtlasEntityDef> toAtlasEntityDefs(List<HierarchicalTypeDefinition<ClassType>> classTypeDefinitions,
AtlasTypeRegistry registry) throws AtlasBaseException {
List<AtlasEntityDef> atlasEntityDefs = new ArrayList<AtlasEntityDef>();
for (HierarchicalTypeDefinition<ClassType> classType : classTypeDefinitions) {
List<AtlasAttributeDef> attrDefs = new ArrayList<AtlasAttributeDef>();
AtlasEntityDef atlasEntityDef = new AtlasEntityDef();
String classTypeDefName = classType.typeName;
atlasEntityDef.setName(classTypeDefName);
atlasEntityDef.setDescription(classType.typeDescription);
atlasEntityDef.setTypeVersion(classType.typeVersion);
atlasEntityDef.setSuperTypes(classType.superTypes);
AttributeDefinition[] attrDefinitions = classType.attributeDefinitions;
for (AttributeDefinition oldAttr : attrDefinitions) {
AtlasAttributeDef newAttr = toAtlasAttributeDef(oldAttr);
// isComposite and reverseAttributeName applicable only for entities/classes.
if (oldAttr.isComposite) {
String attrType = oldAttr.dataTypeName;
attrType = isArrayType(attrType) ? getArrayTypeName(attrType) : attrType;
if (!AtlasTypeUtil.isBuiltInType(attrType)) {
String refAttrName = null;
// 1. Check if attribute datatype is present in payload definition, if present get the typeDefinition,
// check all its attributes and find attribute that matches with classTypeDefName and reverseAttributeName
HierarchicalTypeDefinition<ClassType> refType = findClassType(classTypeDefinitions, attrType);
if (refType != null) {
for (AttributeDefinition refAttr : refType.attributeDefinitions) {
String refAttrDataTypeName = refAttr.dataTypeName;
String refAttrRevAttrName = refAttr.reverseAttributeName;
if (StringUtils.equals(refAttrDataTypeName, classTypeDefName) &&
StringUtils.equals(refAttrRevAttrName, oldAttr.name)) {
refAttrName = refAttr.name;
break;
}
}
}
// 2. Check if attribute present in typeRegistry. If present fetch all attributes associated with the type and
// check revAttrName equals base type attr name AND classTypeDefName equals attribute name
else {
if (registry.isRegisteredType(attrType)) {
AtlasType atlasType = registry.getType(attrType);
if (isEntity(atlasType)) {
AtlasEntityType entityType = (AtlasEntityType) atlasType;
List<AtlasAttributeDef> atlasAttrDefs = entityType.getEntityDef().getAttributeDefs();
for (AtlasAttributeDef attrDef : atlasAttrDefs) {
boolean isForeignKey = entityType.isForeignKeyAttribute(attrDef.getName());
if (isForeignKey) {
AtlasType attribType = entityType.getAttributeType(attrDef.getName());
if (attribType.getTypeCategory() == TypeCategory.ARRAY) {
attribType = ((AtlasArrayType) attribType).getElementType();
}
if (attribType.getTypeCategory() == TypeCategory.ENTITY) {
String revAttrName = ((AtlasEntityType) attribType).
getMappedFromRefAttribute(entityType.getTypeName(), attrDef.getName());
if (StringUtils.equals(classTypeDefName , attrDef.getTypeName()) &&
StringUtils.equals(oldAttr.name, revAttrName)) {
refAttrName = attrDef.getName();
}
}
}
}
}
}
}
if (StringUtils.isNotBlank(refAttrName)) { // ex: hive_table.columns, hive_column.table
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_REF_ATTRIBUTE, refAttrName);
newAttr.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_MAPPED_FROM_REF, params));
} else { // ex: hive_table.partitionKeys, with no reverseAttribute-reference
newAttr.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_FOREIGN_KEY));
}
}
} else if (StringUtils.isNotEmpty(oldAttr.reverseAttributeName)) {
Map<String, Object> params = new HashMap<>();
params.put(CONSTRAINT_PARAM_ON_DELETE, CONSTRAINT_PARAM_VAL_CASCADE);
newAttr.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_FOREIGN_KEY, params));
}
attrDefs.add(newAttr);
}
atlasEntityDef.setAttributeDefs(attrDefs);
atlasEntityDefs.add(atlasEntityDef);
}
return atlasEntityDefs;
}
private static String getArrayTypeName(String attrType) {
String ret = null;
if (isArrayType(attrType)) {
Set<String> typeNames = AtlasTypeUtil.getReferencedTypeNames(attrType);
if (typeNames.size() > 0) {
ret = typeNames.iterator().next();
}
}
return ret;
}
private static List<AtlasEnumElementDef> getAtlasEnumElementDefs(EnumValue[] enums) {
List<AtlasEnumElementDef> ret = new ArrayList<AtlasEnumElementDef>();
for (EnumValue enumElem : enums) {
ret.add(new AtlasEnumElementDef(enumElem.value, null, enumElem.ordinal));
}
return ret;
}
private static EnumValue[] getEnumValues(List<AtlasEnumElementDef> enumDefs) {
List<EnumValue> ret = new ArrayList<EnumValue>();
if (CollectionUtils.isNotEmpty(enumDefs)) {
for (AtlasEnumElementDef enumDef : enumDefs) {
if (enumDef != null) {
ret.add(new EnumValue(enumDef.getValue(), enumDef.getOrdinal()));
}
}
}
return ret.toArray(new EnumValue[ret.size()]);
}
private static AtlasAttributeDef toAtlasAttributeDef(AttributeDefinition attrDefinition) {
AtlasAttributeDef ret = new AtlasAttributeDef();
ret.setName(attrDefinition.name);
ret.setTypeName(attrDefinition.dataTypeName);
ret.setIsIndexable(attrDefinition.isIndexable);
ret.setIsUnique(attrDefinition.isUnique);
// Multiplicity attribute mapping
Multiplicity multiplicity = attrDefinition.multiplicity;
int minCount = multiplicity.lower;
int maxCount = multiplicity.upper;
boolean isUnique = multiplicity.isUnique;
if (minCount == 0) {
ret.setIsOptional(true);
ret.setValuesMinCount(0);
} else {
ret.setIsOptional(false);
ret.setValuesMinCount(minCount);
}
if (maxCount < 2) {
ret.setCardinality(Cardinality.SINGLE);
ret.setValuesMaxCount(1);
} else {
if (!isUnique) {
ret.setCardinality(Cardinality.LIST);
} else {
ret.setCardinality(Cardinality.SET);
}
ret.setValuesMaxCount(maxCount);
}
return ret;
}
private static AttributeDefinition[] getAttributes(AtlasStructDef structDef, AtlasTypeRegistry registry) throws AtlasBaseException {
List<AttributeDefinition> ret = new ArrayList<>();
List<AtlasAttributeDef> attrDefs = structDef.getAttributeDefs();
if (CollectionUtils.isNotEmpty(attrDefs)) {
for (AtlasAttributeDef attrDef : attrDefs) {
String name = attrDef.getName();
String dataTypeName = attrDef.getTypeName();
Boolean isUnique = attrDef.getIsUnique();
Boolean isIndexable = attrDef.getIsIndexable();
String reverseAttribName = null;
boolean isComposite;
// Multiplicity mapping
final int lower;
final int upper;
if (attrDef.getCardinality() == Cardinality.SINGLE) {
lower = attrDef.getIsOptional() ? 0 : 1;
upper = 1;
} else {
if(attrDef.getIsOptional()) {
lower = 0;
} else {
lower = attrDef.getValuesMinCount() < 1 ? 1 : attrDef.getValuesMinCount();
}
upper = attrDef.getValuesMaxCount() < 2 ? Integer.MAX_VALUE : attrDef.getValuesMaxCount();
}
Multiplicity multiplicity = new Multiplicity(lower, upper, Cardinality.SET.equals(attrDef.getCardinality()));
// Constraint checks:
// 1. [ mappedFromRef -> isComposite ]
// 2. [ foreignKey(onDelete=cascade) -> reverseAttribute ]
AtlasStructType structType = (AtlasStructType) registry.getType(structDef.getName());
boolean isForeignKey = structType.isForeignKeyAttribute(attrDef.getName());
boolean isMappedFromRef = structType.isMappedFromRefAttribute(attrDef.getName());
AtlasType attrType = structType.getAttributeType(attrDef.getName());
if (attrType != null && isForeignKey) {
if (attrType.getTypeCategory() == TypeCategory.ARRAY) {
attrType = ((AtlasArrayType) attrType).getElementType();
}
if (attrType.getTypeCategory() == TypeCategory.ENTITY) {
reverseAttribName = ((AtlasStructType) attrType).
getMappedFromRefAttribute(structType.getTypeName(), attrDef.getName());
}
}
isComposite = isMappedFromRef || (isForeignKey && StringUtils.isBlank(reverseAttribName));
ret.add(new AttributeDefinition(name, dataTypeName, multiplicity, isComposite, isUnique, isIndexable, reverseAttribName));
}
}
return ret.toArray(new AttributeDefinition[ret.size()]);
}
private static HierarchicalTypeDefinition<ClassType> findClassType(List<HierarchicalTypeDefinition<ClassType>> classDefs,
String typeName) {
HierarchicalTypeDefinition<ClassType> ret = null;
if (CollectionUtils.isNotEmpty(classDefs)) {
for (HierarchicalTypeDefinition<ClassType> classType : classDefs) {
if (classType.typeName.equalsIgnoreCase(typeName)) {
ret = classType;
}
}
}
return ret;
}
private static boolean isEntity(AtlasType type) {
return type.getTypeCategory() == TypeCategory.ENTITY;
}
}
\ No newline at end of file
...@@ -19,15 +19,26 @@ ...@@ -19,15 +19,26 @@
package org.apache.atlas.web.resources; package org.apache.atlas.web.resources;
import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.core.ResourceContext;
import org.apache.atlas.AtlasClient; import org.apache.atlas.AtlasClient;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.AtlasException; import org.apache.atlas.AtlasException;
import org.apache.atlas.services.MetadataService; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.TypeCategory;
import org.apache.atlas.model.typedef.AtlasClassificationDef;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasEnumDef;
import org.apache.atlas.model.typedef.AtlasStructDef;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.typesystem.TypesDef;
import org.apache.atlas.typesystem.exception.TypeExistsException; import org.apache.atlas.typesystem.exception.TypeExistsException;
import org.apache.atlas.typesystem.types.cache.TypeCache; import org.apache.atlas.typesystem.json.TypesSerialization;
import org.apache.atlas.util.RestUtils;
import org.apache.atlas.utils.AtlasPerfTracer; import org.apache.atlas.utils.AtlasPerfTracer;
import org.apache.atlas.web.rest.TypesREST;
import org.apache.atlas.web.util.Servlets; import org.apache.atlas.web.util.Servlets;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject; import org.codehaus.jettison.json.JSONObject;
...@@ -49,9 +60,7 @@ import javax.ws.rs.WebApplicationException; ...@@ -49,9 +60,7 @@ import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* This class provides RESTful API for Types. * This class provides RESTful API for Types.
...@@ -64,17 +73,18 @@ import java.util.Map; ...@@ -64,17 +73,18 @@ import java.util.Map;
@Path("types") @Path("types")
@Singleton @Singleton
public class TypesResource { public class TypesResource {
private static final Logger LOG = LoggerFactory.getLogger(TypesResource.class); private static final Logger LOG = LoggerFactory.getLogger(TypesResource.class);
private static final Logger PERF_LOG = AtlasPerfTracer.getPerfLogger("rest.TypesResource"); private static final Logger PERF_LOG = AtlasPerfTracer.getPerfLogger("rest.TypesResource");
private static AtlasTypeRegistry typeRegistry;
private final MetadataService metadataService;
@Inject @Inject
public TypesResource(MetadataService metadataService) { public TypesResource(AtlasTypeRegistry typeRegistry) {
this.metadataService = metadataService; this.typeRegistry = typeRegistry;
} }
@Context
private ResourceContext resourceContext;
/** /**
* Submits a type definition corresponding to a given type representing a meta model of a * Submits a type definition corresponding to a given type representing a meta model of a
* domain. Could represent things like Hive Database, Hive Table, etc. * domain. Could represent things like Hive Database, Hive Table, etc.
...@@ -83,7 +93,10 @@ public class TypesResource { ...@@ -83,7 +93,10 @@ public class TypesResource {
@Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON}) @Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
public Response submit(@Context HttpServletRequest request) { public Response submit(@Context HttpServletRequest request) {
TypesREST typesRest = resourceContext.getResource(TypesREST.class);
AtlasPerfTracer perf = null; AtlasPerfTracer perf = null;
JSONArray typesResponse = new JSONArray();
try { try {
if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) { if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesResource.submit()"); perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesResource.submit()");
...@@ -92,12 +105,12 @@ public class TypesResource { ...@@ -92,12 +105,12 @@ public class TypesResource {
final String typeDefinition = Servlets.getRequestPayload(request); final String typeDefinition = Servlets.getRequestPayload(request);
LOG.info("Creating type with definition {} ", typeDefinition); LOG.info("Creating type with definition {} ", typeDefinition);
JSONObject typesJson = metadataService.createType(typeDefinition); AtlasTypesDef createTypesDef = RestUtils.toAtlasTypesDef(typeDefinition, typeRegistry);
final JSONArray typesJsonArray = typesJson.getJSONArray(AtlasClient.TYPES); AtlasTypesDef createdTypesDef = typesRest.createAtlasTypeDefs(createTypesDef);
List<String> typeNames = RestUtils.getTypeNames(createdTypesDef);
JSONArray typesResponse = new JSONArray(); for (int i = 0; i < typeNames.size(); i++) {
for (int i = 0; i < typesJsonArray.length(); i++) { final String name = typeNames.get(i);
final String name = typesJsonArray.getString(i);
typesResponse.put(new JSONObject() {{ typesResponse.put(new JSONObject() {{
put(AtlasClient.NAME, name); put(AtlasClient.NAME, name);
}}); }});
...@@ -107,10 +120,10 @@ public class TypesResource { ...@@ -107,10 +120,10 @@ public class TypesResource {
response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId()); response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId());
response.put(AtlasClient.TYPES, typesResponse); response.put(AtlasClient.TYPES, typesResponse);
return Response.status(ClientResponse.Status.CREATED).entity(response).build(); return Response.status(ClientResponse.Status.CREATED).entity(response).build();
} catch (TypeExistsException e) { } catch (AtlasBaseException e) {
LOG.error("Type already exists", e); LOG.error("Type already exists", e);
throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.CONFLICT)); throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.CONFLICT));
} catch (AtlasException | IllegalArgumentException e) { } catch (IllegalArgumentException e) {
LOG.error("Unable to persist types", e); LOG.error("Unable to persist types", e);
throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST)); throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
} catch (Throwable e) { } catch (Throwable e) {
...@@ -134,7 +147,9 @@ public class TypesResource { ...@@ -134,7 +147,9 @@ public class TypesResource {
@Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON}) @Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
public Response update(@Context HttpServletRequest request) { public Response update(@Context HttpServletRequest request) {
TypesREST typesRest = resourceContext.getResource(TypesREST.class);
AtlasPerfTracer perf = null; AtlasPerfTracer perf = null;
JSONArray typesResponse = new JSONArray();
try { try {
if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) { if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesResource.update()"); perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesResource.update()");
...@@ -143,12 +158,12 @@ public class TypesResource { ...@@ -143,12 +158,12 @@ public class TypesResource {
final String typeDefinition = Servlets.getRequestPayload(request); final String typeDefinition = Servlets.getRequestPayload(request);
LOG.info("Updating type with definition {} ", typeDefinition); LOG.info("Updating type with definition {} ", typeDefinition);
JSONObject typesJson = metadataService.updateType(typeDefinition); AtlasTypesDef updateTypesDef = RestUtils.toAtlasTypesDef(typeDefinition, typeRegistry);
final JSONArray typesJsonArray = typesJson.getJSONArray(AtlasClient.TYPES); AtlasTypesDef updatedTypesDef = typesRest.updateAtlasTypeDefs(updateTypesDef);
List<String> typeNames = RestUtils.getTypeNames(updatedTypesDef);
JSONArray typesResponse = new JSONArray(); for (int i = 0; i < typeNames.size(); i++) {
for (int i = 0; i < typesJsonArray.length(); i++) { final String name = typeNames.get(i);
final String name = typesJsonArray.getString(i);
typesResponse.put(new JSONObject() {{ typesResponse.put(new JSONObject() {{
put(AtlasClient.NAME, name); put(AtlasClient.NAME, name);
}}); }});
...@@ -181,21 +196,49 @@ public class TypesResource { ...@@ -181,21 +196,49 @@ public class TypesResource {
@Path("{typeName}") @Path("{typeName}")
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
public Response getDefinition(@Context HttpServletRequest request, @PathParam("typeName") String typeName) { public Response getDefinition(@Context HttpServletRequest request, @PathParam("typeName") String typeName) {
TypesREST typesRest = resourceContext.getResource(TypesREST.class);
JSONObject response = new JSONObject();
AtlasPerfTracer perf = null; AtlasPerfTracer perf = null;
try { try {
if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) { if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesResource.getDefinition(" + typeName + ")"); perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesResource.getDefinition(" + typeName + ")");
} }
final String typeDefinition = metadataService.getTypeDefinition(typeName); TypeCategory typeCategory = typeRegistry.getType(typeName).getTypeCategory();
TypesDef typesDef = null;
JSONObject response = new JSONObject(); if (typeCategory != null) {
switch (typeCategory) {
case ENUM:
AtlasEnumDef enumDef = typesRest.getEnumDefByName(typeName);
typesDef = RestUtils.toTypesDef(enumDef);
break;
case STRUCT:
AtlasStructDef structDef = typesRest.getStructDefByName(typeName);
typesDef = RestUtils.toTypesDef(structDef, typeRegistry);
break;
case ENTITY:
AtlasEntityDef entityDef = typesRest.getEntityDefByName(typeName);
typesDef = RestUtils.toTypesDef(entityDef, typeRegistry);
break;
case CLASSIFICATION:
AtlasClassificationDef classificationDef = typesRest.getClassificationDefByName(typeName);
typesDef = RestUtils.toTypesDef(classificationDef, typeRegistry);
break;
default:
typesDef = new TypesDef();
break;
}
}
final String typeDefinition = TypesSerialization.toJson(typesDef);
response.put(AtlasClient.TYPENAME, typeName); response.put(AtlasClient.TYPENAME, typeName);
response.put(AtlasClient.DEFINITION, new JSONObject(typeDefinition)); response.put(AtlasClient.DEFINITION, new JSONObject(typeDefinition));
response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId()); response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId());
return Response.ok(response).build(); return Response.ok(response).build();
} catch (AtlasException e) { } catch (AtlasBaseException e) {
LOG.error("Unable to get type definition for type {}", typeName, e); LOG.error("Unable to get type definition for type {}", typeName, e);
throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.NOT_FOUND)); throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.NOT_FOUND));
} catch (JSONException | IllegalArgumentException e) { } catch (JSONException | IllegalArgumentException e) {
...@@ -225,29 +268,26 @@ public class TypesResource { ...@@ -225,29 +268,26 @@ public class TypesResource {
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
public Response getTypesByFilter(@Context HttpServletRequest request, @QueryParam("type") String typeCategory, public Response getTypesByFilter(@Context HttpServletRequest request, @QueryParam("type") String typeCategory,
@QueryParam("supertype") String supertype, @QueryParam("supertype") String supertype,
@QueryParam("notsupertype") String notsupertype) { @QueryParam("notsupertype") String notsupertype) throws AtlasBaseException {
TypesREST typesRest = resourceContext.getResource(TypesREST.class);
JSONObject response = new JSONObject();
AtlasPerfTracer perf = null; AtlasPerfTracer perf = null;
try { try {
if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) { if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesResource.getTypesByFilter(" + typeCategory + ")"); perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesResource.getTypesByFilter(" + typeCategory + ")");
} }
Map<TypeCache.TYPE_FILTER, String> filterMap = new HashMap<>(); List<String> result = RestUtils.getTypeNames(typesRest.getTypeDefHeaders());
addToFilterIfNotEmpty(filterMap, TypeCache.TYPE_FILTER.CATEGORY, typeCategory);
addToFilterIfNotEmpty(filterMap, TypeCache.TYPE_FILTER.SUPERTYPE, supertype);
addToFilterIfNotEmpty(filterMap, TypeCache.TYPE_FILTER.NOT_SUPERTYPE, notsupertype);
List<String> result = metadataService.getTypeNames(filterMap);
JSONObject response = new JSONObject();
response.put(AtlasClient.RESULTS, new JSONArray(result)); response.put(AtlasClient.RESULTS, new JSONArray(result));
response.put(AtlasClient.COUNT, result.size()); response.put(AtlasClient.COUNT, result.size());
response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId()); response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId());
return Response.ok(response).build(); return Response.ok(response).build();
} catch (IllegalArgumentException | AtlasException ie) { } catch (AtlasBaseException e) {
LOG.error("Unsupported typeName while retrieving type list {}", typeCategory); LOG.error("Given search filter did not yield any results");
throw new WebApplicationException( throw new WebApplicationException(
Servlets.getErrorResponse(new Exception("Unsupported type " + typeCategory, ie), Response.Status.BAD_REQUEST)); Servlets.getErrorResponse(new Exception("Given search filter did not yield any results "), Response.Status.BAD_REQUEST));
} catch (Throwable e) { } catch (Throwable e) {
LOG.error("Unable to get types list", e); LOG.error("Unable to get types list", e);
throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR)); throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
...@@ -255,11 +295,4 @@ public class TypesResource { ...@@ -255,11 +295,4 @@ public class TypesResource {
AtlasPerfTracer.log(perf); AtlasPerfTracer.log(perf);
} }
} }
private void addToFilterIfNotEmpty(Map<TypeCache.TYPE_FILTER, String> filterMap, TypeCache.TYPE_FILTER filterType,
String filterValue) {
if (StringUtils.isNotEmpty(filterValue)) {
filterMap.put(filterType, filterValue);
}
}
} }
...@@ -78,7 +78,7 @@ public class TypesJerseyResourceIT extends BaseResourceIT { ...@@ -78,7 +78,7 @@ public class TypesJerseyResourceIT extends BaseResourceIT {
@Test @Test
public void testSubmit() throws Exception { public void testSubmit() throws Exception {
for (HierarchicalTypeDefinition typeDefinition : typeDefinitions) { for (HierarchicalTypeDefinition typeDefinition : typeDefinitions) {
String typesAsJSON = TypesSerialization.toJson(typeDefinition); String typesAsJSON = TypesSerialization.toJson(typeDefinition, false);
System.out.println("typesAsJSON = " + typesAsJSON); System.out.println("typesAsJSON = " + typesAsJSON);
WebResource resource = service.path("api/atlas/types"); WebResource resource = service.path("api/atlas/types");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment