Commit 00fb162d by Mandar Ambawane Committed by nixonrodrigues

ATLAS-3632: Max length validation for business-metadata string attributes and Test cases.

which cover 1.business-metadata typedef creation 2.entity-BM association 3.Max length check Signed-off-by: 's avatarnixonrodrigues <nixon@apache.org>
parent 76011077
...@@ -26,6 +26,7 @@ import org.apache.commons.collections.CollectionUtils; ...@@ -26,6 +26,7 @@ import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.lang.reflect.Array;
import java.util.*; import java.util.*;
import static org.apache.atlas.model.typedef.AtlasBusinessMetadataDef.*; import static org.apache.atlas.model.typedef.AtlasBusinessMetadataDef.*;
...@@ -100,7 +101,7 @@ public class AtlasBusinessMetadataType extends AtlasStructType { ...@@ -100,7 +101,7 @@ public class AtlasBusinessMetadataType extends AtlasStructType {
} }
AtlasBusinessAttribute bmAttribute; AtlasBusinessAttribute bmAttribute;
if (attribute.getAttributeType() instanceof AtlasBuiltInTypes.AtlasStringType) { if (attrType instanceof AtlasBuiltInTypes.AtlasStringType) {
Integer maxStringLength = attribute.getOptionInt(ATTR_MAX_STRING_LENGTH); Integer maxStringLength = attribute.getOptionInt(ATTR_MAX_STRING_LENGTH);
if (maxStringLength == null) { if (maxStringLength == null) {
throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ATTRIBUTE, attributeDef.getName(), "options." + ATTR_MAX_STRING_LENGTH); throw new AtlasBaseException(AtlasErrorCode.MISSING_MANDATORY_ATTRIBUTE, attributeDef.getName(), "options." + ATTR_MAX_STRING_LENGTH);
...@@ -171,5 +172,46 @@ public class AtlasBusinessMetadataType extends AtlasStructType { ...@@ -171,5 +172,46 @@ public class AtlasBusinessMetadataType extends AtlasStructType {
public int getMaxStringLength() { public int getMaxStringLength() {
return maxStringLength; return maxStringLength;
} }
public boolean isValidLength(Object value) {
boolean ret = true;
if (value != null) {
AtlasType attrType = getAttributeType();
if (attrType instanceof AtlasBuiltInTypes.AtlasStringType) {
ret = isValidStringValue(value);
} else if (attrType instanceof AtlasArrayType) {
attrType = ((AtlasArrayType) attrType).getElementType();
if (attrType instanceof AtlasBuiltInTypes.AtlasStringType) {
ret = isValidArrayValue(value);
}
}
}
return ret;
}
private boolean isValidStringValue(Object obj) {
return obj == null || String.valueOf(obj).length() <= this.maxStringLength;
}
private boolean isValidArrayValue(Object obj) {
if (obj instanceof List || obj instanceof Set) {
Collection objList = (Collection) obj;
for (Object element : objList) {
if (!isValidStringValue(element)) {
return false;
}
}
} else if (obj.getClass().isArray()) {
int arrayLen = Array.getLength(obj);
for (int i = 0; i < arrayLen; i++) {
if (!isValidStringValue(Array.get(obj, i))) {
return false;
}
}
}
return true;
}
} }
} }
...@@ -178,6 +178,13 @@ public class AtlasTypeUtil { ...@@ -178,6 +178,13 @@ public class AtlasTypeUtil {
Collections.<AtlasConstraintDef>emptyList()); Collections.<AtlasConstraintDef>emptyList());
} }
public static AtlasAttributeDef createOptionalAttrDef(String name, String dataType, Map<String, String> options, String desc) {
return new AtlasAttributeDef(name, dataType, true,
Cardinality.SINGLE, 0, 1,
false, false, false, "",
Collections.<AtlasConstraintDef>emptyList(), options, desc, 0, null);
}
public static AtlasAttributeDef createRequiredAttrDef(String name, String dataType) { public static AtlasAttributeDef createRequiredAttrDef(String name, String dataType) {
return new AtlasAttributeDef(name, dataType, false, return new AtlasAttributeDef(name, dataType, false,
Cardinality.SINGLE, 1, 1, Cardinality.SINGLE, 1, 1,
...@@ -285,6 +292,13 @@ public class AtlasTypeUtil { ...@@ -285,6 +292,13 @@ public class AtlasTypeUtil {
return new AtlasEntityDef(name, description, version, Arrays.asList(attrDefs), superTypes, options); return new AtlasEntityDef(name, description, version, Arrays.asList(attrDefs), superTypes, options);
} }
public static AtlasBusinessMetadataDef createBusinessMetadataDef(String name, String description, String typeVersion, AtlasAttributeDef... attributeDefs) {
if (attributeDefs == null || attributeDefs.length == 0) {
return new AtlasBusinessMetadataDef(name, description, typeVersion);
}
return new AtlasBusinessMetadataDef(name, description, typeVersion, Arrays.asList(attributeDefs));
}
public static AtlasRelationshipDef createRelationshipTypeDef(String name, public static AtlasRelationshipDef createRelationshipTypeDef(String name,
String description, String description,
String version, String version,
......
...@@ -24,6 +24,7 @@ import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; ...@@ -24,6 +24,7 @@ import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.instance.AtlasObjectId; import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasStruct; import org.apache.atlas.model.instance.AtlasStruct;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef; import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.atlas.model.typedef.AtlasBusinessMetadataDef;
import org.apache.atlas.model.typedef.AtlasClassificationDef; import org.apache.atlas.model.typedef.AtlasClassificationDef;
import org.apache.atlas.model.typedef.AtlasEntityDef; import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasEnumDef; import org.apache.atlas.model.typedef.AtlasEnumDef;
...@@ -58,6 +59,7 @@ import static org.apache.atlas.type.AtlasTypeUtil.createRequiredAttrDef; ...@@ -58,6 +59,7 @@ import static org.apache.atlas.type.AtlasTypeUtil.createRequiredAttrDef;
import static org.apache.atlas.type.AtlasTypeUtil.createStructTypeDef; import static org.apache.atlas.type.AtlasTypeUtil.createStructTypeDef;
import static org.apache.atlas.type.AtlasTypeUtil.createUniqueRequiredAttrDef; import static org.apache.atlas.type.AtlasTypeUtil.createUniqueRequiredAttrDef;
import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId; import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
import static org.apache.atlas.type.AtlasTypeUtil.createBusinessMetadataDef;
/** /**
...@@ -661,6 +663,70 @@ public final class TestUtilsV2 { ...@@ -661,6 +663,70 @@ public final class TestUtilsV2 {
return new AtlasEntityWithExtInfo(entity); return new AtlasEntityWithExtInfo(entity);
} }
public static AtlasTypesDef defineEnumTypes() {
String _description = "_description";
AtlasEnumDef myEnum =
new AtlasEnumDef("ENUM_1", "ENUM_1" + _description, "1.0",
Arrays.asList(
new AtlasEnumElementDef("USER", "Element" + _description, 1),
new AtlasEnumElementDef("ROLE", "Element" + _description, 2),
new AtlasEnumElementDef("GROUP", "Element" + _description, 3)
));
AtlasTypesDef ret = AtlasTypeUtil.getTypesDef(Collections.singletonList(myEnum),
new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
populateSystemAttributes(ret);
return ret;
}
public static AtlasTypesDef defineBusinessMetadataTypes() {
String _description = "_description";
Map<String, String> options = new HashMap<>();
options.put("maxStrLength", "20");
AtlasBusinessMetadataDef bmNoApplicableTypes = createBusinessMetadataDef("bmNoApplicableTypes", _description, "1.0",
createOptionalAttrDef("attr0", "string", options, _description));
AtlasBusinessMetadataDef bmNoAttributes = createBusinessMetadataDef("bmNoAttributes", _description, "1.0", null);
options.put("applicableEntityTypes", "[\"" + DATABASE_TYPE + "\",\"" + TABLE_TYPE + "\"]");
AtlasBusinessMetadataDef bmWithAllTypes = createBusinessMetadataDef("bmWithAllTypes", _description, "1.0",
createOptionalAttrDef("attr1", AtlasBusinessMetadataDef.ATLAS_TYPE_BOOLEAN, options, _description),
createOptionalAttrDef("attr2", AtlasBusinessMetadataDef.ATLAS_TYPE_BYTE, options, _description),
createOptionalAttrDef("attr3", AtlasBusinessMetadataDef.ATLAS_TYPE_SHORT, options, _description),
createOptionalAttrDef("attr4", AtlasBusinessMetadataDef.ATLAS_TYPE_INT, options, _description),
createOptionalAttrDef("attr5", AtlasBusinessMetadataDef.ATLAS_TYPE_LONG, options, _description),
createOptionalAttrDef("attr6", AtlasBusinessMetadataDef.ATLAS_TYPE_FLOAT, options, _description),
createOptionalAttrDef("attr7", AtlasBusinessMetadataDef.ATLAS_TYPE_DOUBLE, options, _description),
createOptionalAttrDef("attr8", AtlasBusinessMetadataDef.ATLAS_TYPE_STRING, options, _description),
createOptionalAttrDef("attr9", AtlasBusinessMetadataDef.ATLAS_TYPE_DATE, options, _description),
createOptionalAttrDef("attr10", "ENUM_1", options, _description));
AtlasBusinessMetadataDef bmWithAllTypesMV = createBusinessMetadataDef("bmWithAllTypesMV", _description, "1.0",
createOptionalAttrDef("attr11", "array<boolean>", options, _description),
createOptionalAttrDef("attr12", "array<byte>", options, _description),
createOptionalAttrDef("attr13", "array<short>", options, _description),
createOptionalAttrDef("attr14", "array<int>", options, _description),
createOptionalAttrDef("attr15", "array<long>", options, _description),
createOptionalAttrDef("attr16", "array<float>", options, _description),
createOptionalAttrDef("attr17", "array<double>", options, _description),
createOptionalAttrDef("attr18", "array<string>", options, _description),
createOptionalAttrDef("attr19", "array<date>", options, _description),
createOptionalAttrDef("attr20", "array<ENUM_1>", options, _description));
AtlasTypesDef ret = AtlasTypeUtil.getTypesDef(new ArrayList<>(),
new ArrayList<>(), new ArrayList<>(),
new ArrayList<>(), new ArrayList<>(),
Arrays.asList(bmNoApplicableTypes, bmNoAttributes, bmWithAllTypes, bmWithAllTypesMV));
populateSystemAttributes(ret);
return ret;
}
public static AtlasTypesDef defineHiveTypes() { public static AtlasTypesDef defineHiveTypes() {
String _description = "_description"; String _description = "_description";
AtlasEntityDef superTypeDefinition = AtlasEntityDef superTypeDefinition =
...@@ -1451,6 +1517,7 @@ public final class TestUtilsV2 { ...@@ -1451,6 +1517,7 @@ public final class TestUtilsV2 {
populateSystemAttributes(typesDef.getClassificationDefs()); populateSystemAttributes(typesDef.getClassificationDefs());
populateSystemAttributes(typesDef.getEntityDefs()); populateSystemAttributes(typesDef.getEntityDefs());
populateSystemAttributes(typesDef.getRelationshipDefs()); populateSystemAttributes(typesDef.getRelationshipDefs());
populateSystemAttributes(typesDef.getBusinessMetadataDefs());
} }
public static void populateSystemAttributes(List<? extends AtlasBaseTypeDef> typeDefs) { public static void populateSystemAttributes(List<? extends AtlasBaseTypeDef> typeDefs) {
......
...@@ -1506,6 +1506,11 @@ public class AtlasEntityStoreV2 implements AtlasEntityStore { ...@@ -1506,6 +1506,11 @@ public class AtlasEntityStoreV2 implements AtlasEntityStore {
if (attrValue != null) { if (attrValue != null) {
attrType.validateValue(attrValue, fieldName, messages); attrType.validateValue(attrValue, fieldName, messages);
boolean isValidLength = bmAttribute.isValidLength(attrValue);
if (!isValidLength) {
messages.add(fieldName + ": Business attribute-value exceeds maximum length limit");
}
} else if (!bmAttribute.getAttributeDef().getIsOptional()) { } else if (!bmAttribute.getAttributeDef().getIsOptional()) {
final boolean isAttrValuePresent; final boolean isAttrValuePresent;
......
...@@ -92,6 +92,8 @@ public class AtlasEntityStoreV2Test extends AtlasEntityTestBase { ...@@ -92,6 +92,8 @@ public class AtlasEntityStoreV2Test extends AtlasEntityTestBase {
AtlasTypesDef[] testTypesDefs = new AtlasTypesDef[] { TestUtilsV2.defineDeptEmployeeTypes(), AtlasTypesDef[] testTypesDefs = new AtlasTypesDef[] { TestUtilsV2.defineDeptEmployeeTypes(),
TestUtilsV2.defineHiveTypes(), TestUtilsV2.defineHiveTypes(),
TestUtilsV2.defineTypeWithNestedCollectionAttributes(), TestUtilsV2.defineTypeWithNestedCollectionAttributes(),
TestUtilsV2.defineEnumTypes(),
TestUtilsV2.defineBusinessMetadataTypes()
}; };
createTypesDef(testTypesDefs); createTypesDef(testTypesDefs);
...@@ -145,7 +147,7 @@ public class AtlasEntityStoreV2Test extends AtlasEntityTestBase { ...@@ -145,7 +147,7 @@ public class AtlasEntityStoreV2Test extends AtlasEntityTestBase {
assertEquals(cost,30); assertEquals(cost,30);
} }
@Test @Test(priority = -1)
public void testCreate() throws Exception { public void testCreate() throws Exception {
init(); init();
...@@ -1229,4 +1231,94 @@ public class AtlasEntityStoreV2Test extends AtlasEntityTestBase { ...@@ -1229,4 +1231,94 @@ public class AtlasEntityStoreV2Test extends AtlasEntityTestBase {
tblEntity = getEntityFromStore(tblEntityGuid); tblEntity = getEntityFromStore(tblEntityGuid);
Assert.assertTrue(tblEntity.getLabels().isEmpty()); Assert.assertTrue(tblEntity.getLabels().isEmpty());
} }
@Test
public void testAddBusinessAttributesStringMaxLengthCheck() throws Exception {
Map<String, Map<String, Object>> bmMapReq = new HashMap<>();
Map<String, Object> bmAttrMapReq = new HashMap<>();
bmAttrMapReq.put("attr8", "01234567890123456789");
bmMapReq.put("bmWithAllTypes", bmAttrMapReq);
entityStore.addOrUpdateBusinessAttributes(dbEntity.getEntity().getGuid(), bmMapReq, false);
AtlasEntityWithExtInfo entity = entityStore.getById(dbEntity.getEntity().getGuid());
Map<String, Map<String, Object>> bmMapRes = entity.getEntity().getBusinessAttributes();
Assert.assertEquals(bmMapReq, bmMapRes);
}
@Test
public void testAddBusinessAttributesStringMaxLengthCheck_2() throws Exception {
Map<String, Map<String, Object>> bmMapReq = new HashMap<>();
Map<String, Object> bmAttrMapReq = new HashMap<>();
bmAttrMapReq.put("attr8", "012345678901234567890");
bmMapReq.put("bmWithAllTypes", bmAttrMapReq);
try {
entityStore.addOrUpdateBusinessAttributes(dbEntity.getEntity().getGuid(), bmMapReq, false);
} catch (AtlasBaseException e) {
Assert.assertEquals(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, e.getAtlasErrorCode());
return;
}
Assert.fail();
}
@Test(dependsOnMethods = "testAddBusinessAttributesStringMaxLengthCheck")
public void testUpdateBusinessAttributesStringMaxLengthCheck() throws Exception {
Map<String, Map<String, Object>> bmMapReq = new HashMap<>();
Map<String, Object> bmAttrMapReq = new HashMap<>();
bmAttrMapReq.put("attr8", "0123456789");
bmMapReq.put("bmWithAllTypes", bmAttrMapReq);
entityStore.addOrUpdateBusinessAttributes(dbEntity.getEntity().getGuid(), bmMapReq, true);
AtlasEntityWithExtInfo entity = entityStore.getById(dbEntity.getEntity().getGuid());
Map<String, Map<String, Object>> bmMapRes = entity.getEntity().getBusinessAttributes();
Assert.assertEquals(bmMapReq, bmMapRes);
}
@Test(dependsOnMethods = "testAddBusinessAttributesStringMaxLengthCheck")
public void testUpdateBusinessAttributesStringMaxLengthCheck_2() throws Exception {
Map<String, Map<String, Object>> bmMapReq = new HashMap<>();
Map<String, Object> bmAttrMapReq = new HashMap<>();
bmAttrMapReq.put("attr8", "012345678901234567890");
bmMapReq.put("bmWithAllTypes", bmAttrMapReq);
try {
entityStore.addOrUpdateBusinessAttributes(dbEntity.getEntity().getGuid(), bmMapReq, true);
} catch (AtlasBaseException e) {
Assert.assertEquals(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, e.getAtlasErrorCode());
return;
}
Assert.fail();
}
@Test(dependsOnMethods = "testAddBusinessAttributesStringMaxLengthCheck")
public void testUpdateBusinessAttributesStringMaxLengthCheck_3() throws Exception {
Map<String, Map<String, Object>> bmAttrMapReq = new HashMap<>();
Map<String, Object> attrValueMapReq = new HashMap<>();
List<String> stringList = new ArrayList<>();
stringList.add("0123456789");
stringList.add("0123456789");
attrValueMapReq.put("attr18", stringList);
bmAttrMapReq.put("bmWithAllTypesMV", attrValueMapReq);
entityStore.addOrUpdateBusinessAttributes(dbEntity.getEntity().getGuid(), bmAttrMapReq, true);
AtlasEntityWithExtInfo entity = entityStore.getById(dbEntity.getEntity().getGuid());
Map<String, Map<String, Object>> bmAttrMapRes = entity.getEntity().getBusinessAttributes();
Assert.assertEquals(bmAttrMapReq, bmAttrMapRes);
}
@Test(dependsOnMethods = "testAddBusinessAttributesStringMaxLengthCheck")
public void testUpdateBusinessAttributesStringMaxLengthCheck_4() throws Exception {
Map<String, Map<String, Object>> bmAttrMapReq = new HashMap<>();
Map<String, Object> attrValueMapReq = new HashMap<>();
List<String> stringList = new ArrayList<>();
stringList.add("0123456789");
stringList.add("012345678901234567890");
attrValueMapReq.put("attr18", stringList);
bmAttrMapReq.put("bmWithAllTypesMV", attrValueMapReq);
try {
entityStore.addOrUpdateBusinessAttributes(dbEntity.getEntity().getGuid(), bmAttrMapReq, true);
} catch (AtlasBaseException e) {
Assert.assertEquals(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, e.getAtlasErrorCode());
return;
}
Assert.fail();
}
} }
\ No newline at end of file
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