| /** |
| * 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.typesystem.types; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Maps; |
| |
| import org.apache.atlas.AtlasException; |
| import org.apache.atlas.typesystem.IReferenceableInstance; |
| import org.apache.atlas.typesystem.ITypedReferenceableInstance; |
| import org.apache.atlas.typesystem.ITypedStruct; |
| import org.apache.atlas.typesystem.Referenceable; |
| import org.apache.atlas.typesystem.Struct; |
| import org.apache.atlas.typesystem.TypesDef; |
| import org.apache.atlas.typesystem.types.utils.TypesUtil; |
| import org.testng.Assert; |
| import org.testng.annotations.BeforeMethod; |
| import org.testng.annotations.Test; |
| |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.Date; |
| import java.util.Map; |
| |
| import static org.apache.atlas.typesystem.types.utils.TypesUtil.createClassTypeDef; |
| import static org.apache.atlas.typesystem.types.utils.TypesUtil.createOptionalAttrDef; |
| import static org.apache.atlas.typesystem.types.utils.TypesUtil.createRequiredAttrDef; |
| |
| public class EnumTest extends BaseTest { |
| |
| @BeforeMethod |
| public void setup() throws Exception { |
| super.setup(); |
| } |
| |
| void defineEnums(TypeSystem ts) throws AtlasException { |
| ts.defineEnumType("HiveObjectType", new EnumValue("GLOBAL", 1), new EnumValue("DATABASE", 2), |
| new EnumValue("TABLE", 3), new EnumValue("PARTITION", 4), new EnumValue("COLUMN", 5)); |
| |
| ts.defineEnumType("PrincipalType", new EnumValue("USER", 1), new EnumValue("ROLE", 2), |
| new EnumValue("GROUP", 3)); |
| |
| ts.defineEnumType("TxnState", new EnumValue("COMMITTED", 1), new EnumValue("ABORTED", 2), |
| new EnumValue("OPEN", 3)); |
| |
| ts.defineEnumType("LockLevel", new EnumValue("DB", 1), new EnumValue("TABLE", 2), |
| new EnumValue("PARTITION", 3)); |
| } |
| |
| @Test |
| public void testTypeUpdate() throws Exception { |
| TypeSystem ts = getTypeSystem(); |
| EnumTypeDefinition etd = new EnumTypeDefinition(newName(), new EnumValue("A", 1)); |
| TypesDef typesDef = getTypesDef(etd); |
| ts.defineTypes(typesDef); |
| |
| //Allow adding new enum |
| etd = new EnumTypeDefinition(etd.name, new EnumValue("A", 1), new EnumValue("B", 2)); |
| typesDef = getTypesDef(etd); |
| ts.updateTypes(typesDef); |
| |
| //Don't allow deleting enum |
| etd = new EnumTypeDefinition(etd.name, new EnumValue("A", 1)); |
| typesDef = getTypesDef(etd); |
| try { |
| ts.updateTypes(typesDef); |
| Assert.fail("Expected TypeUpdateException"); |
| } catch (TypeUpdateException e) { |
| //assert that type is not updated when validation fails |
| EnumType enumType = ts.getDataType(EnumType.class, etd.name); |
| Assert.assertEquals(enumType.values().size(), 2); |
| } |
| |
| //Don't allow changing ordinal of existing enum value |
| etd = new EnumTypeDefinition(etd.name, new EnumValue("A", 2)); |
| typesDef = getTypesDef(etd); |
| try { |
| ts.updateTypes(typesDef); |
| Assert.fail("Expected TypeUpdateException"); |
| } catch (TypeUpdateException e) { |
| //expected |
| } |
| } |
| |
| private TypesDef getTypesDef(EnumTypeDefinition enumTypeDefinition) { |
| return TypesUtil.getTypesDef(ImmutableList.of(enumTypeDefinition), ImmutableList.<StructTypeDefinition>of(), |
| ImmutableList.<HierarchicalTypeDefinition<TraitType>>of(), |
| ImmutableList.<HierarchicalTypeDefinition<ClassType>>of()); |
| } |
| |
| protected void fillStruct(Struct s) throws AtlasException { |
| s.set("a", 1); |
| s.set("b", true); |
| s.set("c", (byte) 1); |
| s.set("d", (short) 2); |
| s.set("e", 1); |
| s.set("f", 1); |
| s.set("g", 1L); |
| s.set("h", 1.0f); |
| s.set("i", 1.0); |
| s.set("j", BigInteger.valueOf(1L)); |
| s.set("k", new BigDecimal(1)); |
| s.set("l", new Date(1418265358440L)); |
| s.set("m", Lists.asList(1, new Integer[]{1})); |
| s.set("n", Lists.asList(BigDecimal.valueOf(1.1), new BigDecimal[]{BigDecimal.valueOf(1.1)})); |
| Map<String, Double> hm = Maps.newHashMap(); |
| hm.put("a", 1.0); |
| hm.put("b", 2.0); |
| s.set("o", hm); |
| s.set("enum1", "GLOBAL"); |
| s.set("enum2", 1); |
| s.set("enum3", "COMMITTED"); |
| s.set("enum4", 3); |
| } |
| |
| protected Struct createStructWithEnum(String typeName) throws AtlasException { |
| Struct s = new Struct(typeName); |
| fillStruct(s); |
| return s; |
| } |
| |
| protected Referenceable createInstanceWithEnum(String typeName) throws AtlasException { |
| Referenceable r = new Referenceable(typeName); |
| fillStruct(r); |
| return r; |
| } |
| |
| protected ClassType defineClassTypeWithEnum(TypeSystem ts) throws AtlasException { |
| return ts.defineClassType( |
| createClassTypeDef("t4", ImmutableSet.<String>of(), createRequiredAttrDef("a", DataTypes.INT_TYPE), |
| createOptionalAttrDef("b", DataTypes.BOOLEAN_TYPE), |
| createOptionalAttrDef("c", DataTypes.BYTE_TYPE), |
| createOptionalAttrDef("d", DataTypes.SHORT_TYPE), |
| createOptionalAttrDef("enum1", ts.getDataType(EnumType.class, "HiveObjectType")), |
| createOptionalAttrDef("e", DataTypes.INT_TYPE), createOptionalAttrDef("f", DataTypes.INT_TYPE), |
| createOptionalAttrDef("g", DataTypes.LONG_TYPE), |
| createOptionalAttrDef("enum2", ts.getDataType(EnumType.class, "PrincipalType")), |
| createOptionalAttrDef("h", DataTypes.FLOAT_TYPE), |
| createOptionalAttrDef("i", DataTypes.DOUBLE_TYPE), |
| createOptionalAttrDef("j", DataTypes.BIGINTEGER_TYPE), |
| createOptionalAttrDef("k", DataTypes.BIGDECIMAL_TYPE), |
| createOptionalAttrDef("enum3", ts.getDataType(EnumType.class, "TxnState")), |
| createOptionalAttrDef("l", DataTypes.DATE_TYPE), |
| createOptionalAttrDef("m", ts.defineArrayType(DataTypes.INT_TYPE)), |
| createOptionalAttrDef("n", ts.defineArrayType(DataTypes.BIGDECIMAL_TYPE)), |
| createOptionalAttrDef("o", ts.defineMapType(DataTypes.STRING_TYPE, DataTypes.DOUBLE_TYPE)), |
| createOptionalAttrDef("enum4", ts.getDataType(EnumType.class, "LockLevel")))); |
| } |
| |
| @Test |
| public void testStruct() throws AtlasException { |
| TypeSystem ts = getTypeSystem(); |
| defineEnums(ts); |
| StructType structType = ts.defineStructType("ts", true, createRequiredAttrDef("a", DataTypes.INT_TYPE), |
| createOptionalAttrDef("b", DataTypes.BOOLEAN_TYPE), createOptionalAttrDef("c", DataTypes.BYTE_TYPE), |
| createOptionalAttrDef("d", DataTypes.SHORT_TYPE), |
| createOptionalAttrDef("enum1", ts.getDataType(EnumType.class, "HiveObjectType")), |
| createOptionalAttrDef("e", DataTypes.INT_TYPE), createOptionalAttrDef("f", DataTypes.INT_TYPE), |
| createOptionalAttrDef("g", DataTypes.LONG_TYPE), |
| createOptionalAttrDef("enum2", ts.getDataType(EnumType.class, "PrincipalType")), |
| createOptionalAttrDef("h", DataTypes.FLOAT_TYPE), createOptionalAttrDef("i", DataTypes.DOUBLE_TYPE), |
| createOptionalAttrDef("j", DataTypes.BIGINTEGER_TYPE), |
| createOptionalAttrDef("k", DataTypes.BIGDECIMAL_TYPE), |
| createOptionalAttrDef("enum3", ts.getDataType(EnumType.class, "TxnState")), |
| createOptionalAttrDef("l", DataTypes.DATE_TYPE), |
| createOptionalAttrDef("m", ts.defineArrayType(DataTypes.INT_TYPE)), |
| createOptionalAttrDef("n", ts.defineArrayType(DataTypes.BIGDECIMAL_TYPE)), |
| createOptionalAttrDef("o", ts.defineMapType(DataTypes.STRING_TYPE, DataTypes.DOUBLE_TYPE)), |
| createOptionalAttrDef("enum4", ts.getDataType(EnumType.class, "LockLevel"))); |
| |
| Struct s = createStructWithEnum("ts"); |
| ITypedStruct typedS = structType.convert(s, Multiplicity.REQUIRED); |
| Assert.assertEquals(typedS.toString(), "{\n" + |
| "\ta : \t1\n" + |
| "\tb : \ttrue\n" + |
| "\tc : \t1\n" + |
| "\td : \t2\n" + |
| "\tenum1 : \tGLOBAL\n" + |
| "\te : \t1\n" + |
| "\tf : \t1\n" + |
| "\tg : \t1\n" + |
| "\tenum2 : \tUSER\n" + |
| "\th : \t1.0\n" + |
| "\ti : \t1.0\n" + |
| "\tj : \t1\n" + |
| "\tk : \t1\n" + |
| "\tenum3 : \tCOMMITTED\n" + |
| "\tl : \t" + TEST_DATE + "\n" + |
| "\tm : \t[1, 1]\n" + |
| "\tn : \t[1.1, 1.1]\n" + |
| "\to : \t{a=1.0, b=2.0}\n" + |
| "\tenum4 : \tPARTITION\n" + |
| "}"); |
| } |
| |
| @Test |
| public void testClass() throws AtlasException { |
| TypeSystem ts = getTypeSystem(); |
| defineEnums(ts); |
| ClassType clsType = defineClassTypeWithEnum(ts); |
| |
| IReferenceableInstance r = createInstanceWithEnum("t4"); |
| ITypedReferenceableInstance typedR = clsType.convert(r, Multiplicity.REQUIRED); |
| Assert.assertEquals(typedR.toString(), "{\n" + |
| "\tid : (type: t4, id: <unassigned>)\n" + |
| "\ta : \t1\n" + |
| "\tb : \ttrue\n" + |
| "\tc : \t1\n" + |
| "\td : \t2\n" + |
| "\tenum1 : \tGLOBAL\n" + |
| "\te : \t1\n" + |
| "\tf : \t1\n" + |
| "\tg : \t1\n" + |
| "\tenum2 : \tUSER\n" + |
| "\th : \t1.0\n" + |
| "\ti : \t1.0\n" + |
| "\tj : \t1\n" + |
| "\tk : \t1\n" + |
| "\tenum3 : \tCOMMITTED\n" + |
| "\tl : \t" + TEST_DATE + "\n" + |
| "\tm : \t[1, 1]\n" + |
| "\tn : \t[1.1, 1.1]\n" + |
| "\to : \t{a=1.0, b=2.0}\n" + |
| "\tenum4 : \tPARTITION\n" + |
| "}"); |
| } |
| } |