| /** |
| * 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 |
| * |
| * 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.apache.atlas.web.resources; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import com.sun.jersey.core.util.MultivaluedMapImpl; |
| import org.apache.atlas.AtlasClient; |
| import org.apache.atlas.AtlasServiceException; |
| import org.apache.atlas.typesystem.TypesDef; |
| import org.apache.atlas.typesystem.json.TypesSerialization; |
| 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.DataTypes; |
| import org.apache.atlas.typesystem.types.EnumTypeDefinition; |
| 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.codehaus.jettison.json.JSONArray; |
| import org.codehaus.jettison.json.JSONObject; |
| import org.testng.Assert; |
| import org.testng.annotations.AfterClass; |
| import org.testng.annotations.BeforeClass; |
| import org.testng.annotations.Test; |
| |
| import javax.ws.rs.core.MultivaluedMap; |
| import javax.ws.rs.core.Response; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import static org.apache.atlas.typesystem.types.utils.TypesUtil.createOptionalAttrDef; |
| import static org.testng.Assert.assertEquals; |
| import static org.testng.Assert.assertNotNull; |
| import static org.testng.Assert.fail; |
| |
| /** |
| * Integration test for types jersey resource. |
| */ |
| public class TypesJerseyResourceIT extends BaseResourceIT { |
| |
| private List<HierarchicalTypeDefinition> typeDefinitions; |
| |
| @BeforeClass |
| public void setUp() throws Exception { |
| super.setUp(); |
| |
| typeDefinitions = createHiveTypes(); |
| } |
| |
| @AfterClass |
| public void tearDown() throws Exception { |
| typeDefinitions.clear(); |
| } |
| |
| @Test |
| public void testSubmit() throws Exception { |
| for (HierarchicalTypeDefinition typeDefinition : typeDefinitions) { |
| try{ |
| atlasClientV1.getType(typeDefinition.typeName); |
| } catch (AtlasServiceException ase){ |
| String typesAsJSON = TypesSerialization.toJson(typeDefinition, false); |
| System.out.println("typesAsJSON = " + typesAsJSON); |
| |
| JSONObject response = atlasClientV1.callAPIWithBody(AtlasClient.API.CREATE_TYPE, typesAsJSON); |
| Assert.assertNotNull(response); |
| |
| |
| JSONArray typesAdded = response.getJSONArray(AtlasClient.TYPES); |
| assertEquals(typesAdded.length(), 1); |
| assertEquals(typesAdded.getJSONObject(0).getString(NAME), typeDefinition.typeName); |
| Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID));} |
| } |
| } |
| |
| @Test |
| public void testDuplicateSubmit() throws Exception { |
| HierarchicalTypeDefinition<ClassType> type = TypesUtil.createClassTypeDef(randomString(), |
| ImmutableSet.<String>of(), TypesUtil.createUniqueRequiredAttrDef(NAME, DataTypes.STRING_TYPE)); |
| TypesDef typesDef = |
| TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(), ImmutableList.<StructTypeDefinition>of(), |
| ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(), ImmutableList.of(type)); |
| atlasClientV1.createType(typesDef); |
| |
| try { |
| atlasClientV1.createType(typesDef); |
| fail("Expected 409"); |
| } catch (AtlasServiceException e) { |
| assertEquals(e.getStatus().getStatusCode(), Response.Status.CONFLICT.getStatusCode()); |
| } |
| } |
| |
| @Test |
| public void testUpdate() throws Exception { |
| HierarchicalTypeDefinition<ClassType> typeDefinition = TypesUtil |
| .createClassTypeDef(randomString(), ImmutableSet.<String>of(), |
| TypesUtil.createUniqueRequiredAttrDef(NAME, DataTypes.STRING_TYPE)); |
| List<String> typesCreated = atlasClientV1.createType(TypesSerialization.toJson(typeDefinition, false)); |
| assertEquals(typesCreated.size(), 1); |
| assertEquals(typesCreated.get(0), typeDefinition.typeName); |
| |
| //Add attribute description |
| typeDefinition = TypesUtil.createClassTypeDef(typeDefinition.typeName, |
| ImmutableSet.<String>of(), |
| TypesUtil.createUniqueRequiredAttrDef(NAME, DataTypes.STRING_TYPE), |
| createOptionalAttrDef(DESCRIPTION, DataTypes.STRING_TYPE)); |
| TypesDef typeDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(), |
| ImmutableList.<StructTypeDefinition>of(), ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(), |
| ImmutableList.of(typeDefinition)); |
| List<String> typesUpdated = atlasClientV1.updateType(typeDef); |
| assertEquals(typesUpdated.size(), 1); |
| Assert.assertTrue(typesUpdated.contains(typeDefinition.typeName)); |
| |
| TypesDef updatedTypeDef = atlasClientV1.getType(typeDefinition.typeName); |
| assertNotNull(updatedTypeDef); |
| |
| HierarchicalTypeDefinition<ClassType> updatedType = updatedTypeDef.classTypesAsJavaList().get(0); |
| assertEquals(updatedType.attributeDefinitions.length, 2); |
| } |
| |
| @Test(dependsOnMethods = "testSubmit") |
| public void testGetDefinition() throws Exception { |
| for (HierarchicalTypeDefinition typeDefinition : typeDefinitions) { |
| System.out.println("typeName = " + typeDefinition.typeName); |
| |
| JSONObject response = atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API.LIST_TYPES, null, typeDefinition.typeName); |
| |
| Assert.assertNotNull(response); |
| Assert.assertNotNull(response.get(AtlasClient.DEFINITION)); |
| Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID)); |
| |
| String typesJson = response.getString(AtlasClient.DEFINITION); |
| final TypesDef typesDef = TypesSerialization.fromJson(typesJson); |
| List<HierarchicalTypeDefinition<ClassType>> hierarchicalTypeDefinitions = typesDef.classTypesAsJavaList(); |
| for (HierarchicalTypeDefinition<ClassType> classType : hierarchicalTypeDefinitions) { |
| for (AttributeDefinition attrDef : classType.attributeDefinitions) { |
| if (NAME.equals(attrDef.name)) { |
| assertEquals(attrDef.isIndexable, true); |
| assertEquals(attrDef.isUnique, true); |
| } |
| } |
| } |
| } |
| } |
| |
| @Test(expectedExceptions = AtlasServiceException.class) |
| public void testGetDefinitionForNonexistentType() throws Exception { |
| JSONObject response = atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API.LIST_TYPES, null, "blah"); |
| } |
| |
| @Test(dependsOnMethods = "testSubmit") |
| public void testGetTypeNames() throws Exception { |
| JSONObject response = atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API.LIST_TYPES, null, (String[]) null); |
| Assert.assertNotNull(response); |
| |
| Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID)); |
| |
| final JSONArray list = response.getJSONArray(AtlasClient.RESULTS); |
| Assert.assertNotNull(list); |
| |
| //Verify that primitive and core types are not returned |
| String typesString = list.join(" "); |
| Assert.assertFalse(typesString.contains(" \"__IdType\" ")); |
| Assert.assertFalse(typesString.contains(" \"string\" ")); |
| } |
| |
| @Test |
| public void testGetTraitNames() throws Exception { |
| String[] traitsAdded = addTraits(); |
| |
| MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); |
| queryParams.add("type", DataTypes.TypeCategory.TRAIT.name()); |
| |
| JSONObject response = atlasClientV1.callAPIWithQueryParams(AtlasClient.API.LIST_TYPES, queryParams); |
| Assert.assertNotNull(response); |
| |
| Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID)); |
| |
| final JSONArray list = response.getJSONArray(AtlasClient.RESULTS); |
| Assert.assertNotNull(list); |
| Assert.assertTrue(list.length() >= traitsAdded.length); |
| } |
| |
| @Test |
| public void testListTypesByFilter() throws Exception { |
| AttributeDefinition attr = TypesUtil.createOptionalAttrDef("attr", DataTypes.STRING_TYPE); |
| String a = createType(TypesSerialization.toJson( |
| TypesUtil.createClassTypeDef("A" + randomString(), ImmutableSet.<String>of(), attr), false)).get(0); |
| String a1 = createType(TypesSerialization.toJson( |
| TypesUtil.createClassTypeDef("A1" + randomString(), ImmutableSet.of(a), attr), false)).get(0); |
| String b = createType(TypesSerialization.toJson( |
| TypesUtil.createClassTypeDef("B" + randomString(), ImmutableSet.<String>of(), attr), false)).get(0); |
| String c = createType(TypesSerialization.toJson( |
| TypesUtil.createClassTypeDef("C" + randomString(), ImmutableSet.of(a, b), attr), false)).get(0); |
| |
| List<String> results = atlasClientV1.listTypes(DataTypes.TypeCategory.CLASS, a, b); |
| assertEquals(results, Arrays.asList(a1), "Results: " + results); |
| } |
| |
| private String[] addTraits() throws Exception { |
| String[] traitNames = {"class_trait", "secure_trait", "pii_trait", "ssn_trait", "salary_trait", "sox_trait",}; |
| |
| for (String traitName : traitNames) { |
| HierarchicalTypeDefinition<TraitType> traitTypeDef = |
| TypesUtil.createTraitTypeDef(traitName, ImmutableSet.<String>of()); |
| String json = TypesSerialization$.MODULE$.toJson(traitTypeDef, true); |
| createType(json); |
| } |
| |
| return traitNames; |
| } |
| |
| private List<HierarchicalTypeDefinition> createHiveTypes() throws Exception { |
| ArrayList<HierarchicalTypeDefinition> typeDefinitions = new ArrayList<>(); |
| |
| HierarchicalTypeDefinition<ClassType> databaseTypeDefinition = TypesUtil |
| .createClassTypeDef("database", ImmutableSet.<String>of(), |
| TypesUtil.createUniqueRequiredAttrDef(NAME, DataTypes.STRING_TYPE), |
| TypesUtil.createRequiredAttrDef(DESCRIPTION, DataTypes.STRING_TYPE), |
| TypesUtil.createRequiredAttrDef(QUALIFIED_NAME, DataTypes.STRING_TYPE)); |
| typeDefinitions.add(databaseTypeDefinition); |
| |
| HierarchicalTypeDefinition<ClassType> tableTypeDefinition = TypesUtil |
| .createClassTypeDef("table", ImmutableSet.<String>of(), |
| TypesUtil.createUniqueRequiredAttrDef(NAME, DataTypes.STRING_TYPE), |
| TypesUtil.createRequiredAttrDef(DESCRIPTION, DataTypes.STRING_TYPE), |
| TypesUtil.createRequiredAttrDef(QUALIFIED_NAME, DataTypes.STRING_TYPE), |
| createOptionalAttrDef("columnNames", DataTypes.arrayTypeName(DataTypes.STRING_TYPE)), |
| createOptionalAttrDef("created", DataTypes.DATE_TYPE), |
| createOptionalAttrDef("parameters", |
| DataTypes.mapTypeName(DataTypes.STRING_TYPE, DataTypes.STRING_TYPE)), |
| TypesUtil.createRequiredAttrDef("type", DataTypes.STRING_TYPE), |
| new AttributeDefinition("database", "database", Multiplicity.REQUIRED, false, "database")); |
| typeDefinitions.add(tableTypeDefinition); |
| |
| HierarchicalTypeDefinition<TraitType> fetlTypeDefinition = TypesUtil |
| .createTraitTypeDef("fetl", ImmutableSet.<String>of(), |
| TypesUtil.createRequiredAttrDef("level", DataTypes.INT_TYPE)); |
| typeDefinitions.add(fetlTypeDefinition); |
| |
| return typeDefinitions; |
| } |
| } |