This is an automated email from the ASF dual-hosted git repository. sarath pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/atlas.git
The following commit(s) were added to refs/heads/master by this push: new 14037ee ATLAS-3031: UI : Allow user to export the lineage in PNG or JPEG format 14037ee is described below commit 14037eed5c380006b0d622842677e362057a433a Author: lma <constance.m...@gmail.com> AuthorDate: Thu Mar 28 16:53:11 2019 -0700 ATLAS-3031: UI : Allow user to export the lineage in PNG or JPEG format Signed-off-by: Sarath Subramanian <ssubraman...@hortonworks.com> --- .../graphdb/janus/AtlasJanusElement.java | 14 ++- .../java/org/apache/atlas/type/AtlasArrayType.java | 8 +- .../test/java/org/apache/atlas/TestUtilsV2.java | 37 +++++++ .../apache/atlas/repository/graph/GraphHelper.java | 4 - .../store/graph/v2/AtlasGraphUtilsV2.java | 5 +- .../store/graph/v2/EntityGraphMapper.java | 115 ++++++++++++--------- .../store/graph/v2/EntityGraphRetriever.java | 22 ++-- .../store/graph/v2/AtlasComplexAttributesTest.java | 50 ++++++++- 8 files changed, 177 insertions(+), 78 deletions(-) diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusElement.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusElement.java index aa92672..a9cc5a6 100644 --- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusElement.java +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusElement.java @@ -109,7 +109,14 @@ public class AtlasJanusElement<T extends Element> implements AtlasElement { @Override public void setProperty(String propertyName, Object value) { try { - getWrappedElement().property(propertyName, value); + if (value == null) { + Object existingVal = getProperty(propertyName, Object.class); + if (existingVal != null) { + removeProperty(propertyName); + } + } else { + getWrappedElement().property(propertyName, value); + } } catch(SchemaViolationException e) { throw new AtlasSchemaViolationException(e); } @@ -157,9 +164,6 @@ public class AtlasJanusElement<T extends Element> implements AtlasElement { @Override public List<String> getListProperty(String propertyName) { List<String> value = getProperty(propertyName, List.class); - if (value == null) { - return Collections.emptyList(); - } return value; } @@ -200,7 +204,7 @@ public class AtlasJanusElement<T extends Element> implements AtlasElement { List<String> value = getListProperty(propertyName); - if (value.isEmpty()) { + if (value == null || value.isEmpty()) { return (List<V>)value; } diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasArrayType.java b/intg/src/main/java/org/apache/atlas/type/AtlasArrayType.java index ac1206f..6147eee 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasArrayType.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasArrayType.java @@ -154,9 +154,9 @@ public class AtlasArrayType extends AtlasType { boolean ret = true; if (val1 == null) { - ret = isEmptyArrayValue(val2); + ret = val2 == null; } else if (val2 == null) { - ret = isEmptyArrayValue(val1); + ret = false; } else { if (val1.getClass().isArray() && val2.getClass().isArray()) { int len = Array.getLength(val1); @@ -510,9 +510,7 @@ public class AtlasArrayType extends AtlasType { } private boolean isEmptyArrayValue(Object val) { - if (val == null) { - return true; - } else if (val instanceof Collection) { + if (val instanceof Collection) { return ((Collection) val).isEmpty(); } else if (val.getClass().isArray()) { return Array.getLength(val) == 0; diff --git a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java index 093105b..a109f6a 100755 --- a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java +++ b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java @@ -553,6 +553,7 @@ public final class TestUtilsV2 { public static final String SERDE_TYPE = "serdeType"; public static final String COLUMNS_MAP = "columnsMap"; public static final String COLUMNS_ATTR_NAME = "columns"; + public static final String ENTITY_TYPE_WITH_SIMPLE_ATTR = "entity_with_simple_attr"; public static final String ENTITY_TYPE_WITH_NESTED_COLLECTION_ATTR = "entity_with_nested_collection_attr"; public static final String ENTITY_TYPE_WITH_COMPLEX_COLLECTION_ATTR = "entity_with_complex_collection_attr"; public static final String ENTITY_TYPE_WITH_COMPLEX_COLLECTION_ATTR_DELETE = "entity_with_complex_collection_attr_delete"; @@ -621,6 +622,42 @@ public final class TestUtilsV2 { return ret; } + public static AtlasTypesDef defineSimpleAttrType() { + AtlasEntityDef simpleAttributesEntityType = + createClassTypeDef(ENTITY_TYPE_WITH_SIMPLE_ATTR, ENTITY_TYPE_WITH_SIMPLE_ATTR + "_description", null, + createUniqueRequiredAttrDef("name", "string"), + + new AtlasAttributeDef("stringAtrr", "string", + true, + SINGLE, 1, 1, + false, false, false, null), + + new AtlasAttributeDef("arrayOfStrings", + "array<string>", true, SINGLE, 1, 1, + false, false, false, null), + + new AtlasAttributeDef("mapOfStrings", "map<string,string>", + true, SINGLE, 1,1, false, false, false, null) + ); + + AtlasTypesDef ret = AtlasTypeUtil.getTypesDef(Collections.<AtlasEnumDef>emptyList(), + Collections.<AtlasStructDef>emptyList(), + Collections.<AtlasClassificationDef>emptyList(), + Collections.singletonList(simpleAttributesEntityType)); + + return ret; + } + + public static AtlasEntityWithExtInfo createSimpleAttrTypeEntity() { + AtlasEntity entity = new AtlasEntity(ENTITY_TYPE_WITH_SIMPLE_ATTR); + + entity.setAttribute(NAME, ENTITY_TYPE_WITH_SIMPLE_ATTR); + entity.setAttribute("stringAtrr", "DummyThree"); + entity.setAttribute("arrayOfStrings", Arrays.asList("DummyOne", "DummyTwo")); + entity.setAttribute("mapOfStrings", Collections.singletonMap("one", "DummyString")); + + return new AtlasEntityWithExtInfo(entity); + } public static AtlasTypesDef defineHiveTypes() { String _description = "_description"; diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java b/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java index fde93b5..449f382 100755 --- a/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java +++ b/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java @@ -1587,10 +1587,6 @@ public final class GraphHelper { public static Map<String, Object> getPrimitiveMap(AtlasVertex instanceVertex, String propertyName) { Map<String, Object> ret = instanceVertex.getProperty(AtlasGraphUtilsV2.encodePropertyKey(propertyName), Map.class); - if (ret == null) { - ret = new HashMap<>(); - } - return ret; } diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java index e8d61d1..2882f09 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java @@ -228,12 +228,11 @@ public class AtlasGraphUtilsV2 { Object existingValue = element.getProperty(propertyName, Object.class); - if (value == null || (value instanceof Collection && ((Collection)value).isEmpty())) { + if (value == null) { if (existingValue != null) { if (LOG.isDebugEnabled()) { LOG.debug("Removing property {} from {}", propertyName, toString(element)); } - element.removeProperty(propertyName); } } else { @@ -242,7 +241,7 @@ public class AtlasGraphUtilsV2 { LOG.debug("Setting property {} in {}", propertyName, toString(element)); } - if ( value instanceof Date) { + if (value instanceof Date) { Long encodedValue = ((Date) value).getTime(); element.setProperty(propertyName, encodedValue); } else { diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java index 31b20ff..4f93c8f 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java @@ -947,52 +947,63 @@ public class EntityGraphMapper { boolean isReference = isReference(mapType.getValueType()); boolean isSoftReference = ctx.getAttribute().getAttributeDef().isSoftReferenced(); - if (MapUtils.isNotEmpty(newVal)) { - String propertyName = ctx.getVertexProperty(); + boolean isNewValNull = newVal == null; - if (isReference) { - for (Map.Entry<Object, Object> entry : newVal.entrySet()) { - String key = entry.getKey().toString(); - AtlasEdge existingEdge = isSoftReference ? null : getEdgeIfExists(mapType, currentMap, key); + if (isNewValNull) { + newVal = new HashMap<>(); + } - AttributeMutationContext mapCtx = new AttributeMutationContext(ctx.getOp(), ctx.getReferringVertex(), attribute, entry.getValue(), - propertyName, mapType.getValueType(), existingEdge); - // Add/Update/Remove property value - Object newEntry = mapCollectionElementsToVertex(mapCtx, context); + String propertyName = ctx.getVertexProperty(); - if (!isSoftReference && newEntry instanceof AtlasEdge) { - AtlasEdge edge = (AtlasEdge) newEntry; + if (isReference) { + for (Map.Entry<Object, Object> entry : newVal.entrySet()) { + String key = entry.getKey().toString(); + AtlasEdge existingEdge = isSoftReference ? null : getEdgeIfExists(mapType, currentMap, key); - edge.setProperty(ATTRIBUTE_KEY_PROPERTY_KEY, key); + AttributeMutationContext mapCtx = new AttributeMutationContext(ctx.getOp(), ctx.getReferringVertex(), attribute, entry.getValue(), + propertyName, mapType.getValueType(), existingEdge); + // Add/Update/Remove property value + Object newEntry = mapCollectionElementsToVertex(mapCtx, context); - // If value type indicates this attribute is a reference, and the attribute has an inverse reference attribute, - // update the inverse reference value. - AtlasAttribute inverseRefAttribute = attribute.getInverseRefAttribute(); + if (!isSoftReference && newEntry instanceof AtlasEdge) { + AtlasEdge edge = (AtlasEdge) newEntry; - if (inverseRefAttribute != null) { - addInverseReference(context, inverseRefAttribute, edge, getRelationshipAttributes(ctx.getValue())); - } + edge.setProperty(ATTRIBUTE_KEY_PROPERTY_KEY, key); - updateInConsistentOwnedMapVertices(ctx, mapType, newEntry); + // If value type indicates this attribute is a reference, and the attribute has an inverse reference attribute, + // update the inverse reference value. + AtlasAttribute inverseRefAttribute = attribute.getInverseRefAttribute(); - newMap.put(key, newEntry); + if (inverseRefAttribute != null) { + addInverseReference(context, inverseRefAttribute, edge, getRelationshipAttributes(ctx.getValue())); } - if (isSoftReference) { - newMap.put(key, newEntry); - } + updateInConsistentOwnedMapVertices(ctx, mapType, newEntry); + + newMap.put(key, newEntry); + } + + if (isSoftReference) { + newMap.put(key, newEntry); } + } - Map<String, Object> finalMap = removeUnusedMapEntries(attribute, ctx.getReferringVertex(), currentMap, newMap); - newMap.putAll(finalMap); + Map<String, Object> finalMap = removeUnusedMapEntries(attribute, ctx.getReferringVertex(), currentMap, newMap); + newMap.putAll(finalMap); + } else { + // primitive type map + if (isNewValNull) { + ctx.getReferringVertex().setProperty(propertyName, null); } else { - // primitive type map ctx.getReferringVertex().setProperty(propertyName, new HashMap<>(newVal)); - - newVal.forEach((key, value) -> newMap.put(key.toString(), value)); } + newVal.forEach((key, value) -> newMap.put(key.toString(), value)); + } - if (isSoftReference) { + if (isSoftReference) { + if (isNewValNull) { + ctx.getReferringVertex().setProperty(propertyName,null); + } else { ctx.getReferringVertex().setProperty(propertyName, new HashMap<>(newMap)); } } @@ -1019,6 +1030,7 @@ public class EntityGraphMapper { Cardinality cardinality = attribute.getAttributeDef().getCardinality(); List<Object> newElementsCreated = new ArrayList<>(); List<Object> currentElements; + boolean isNewElementsNull = newElements == null; if (isReference && !isSoftReference) { currentElements = (List) getCollectionElementsUsingRelationship(ctx.getReferringVertex(), attribute); @@ -1026,28 +1038,30 @@ public class EntityGraphMapper { currentElements = (List) getArrayElementsProperty(elementType, isSoftReference, ctx.getReferringVertex(), ctx.getVertexProperty()); } - if (CollectionUtils.isNotEmpty(newElements)) { - if (cardinality == SET) { - newElements = (List) newElements.stream().distinct().collect(Collectors.toList()); - } + if (isNewElementsNull) { + newElements = new ArrayList(); + } - for (int index = 0; index < newElements.size(); index++) { - AtlasEdge existingEdge = (isSoftReference) ? null : getEdgeAt(currentElements, index, elementType); - AttributeMutationContext arrCtx = new AttributeMutationContext(ctx.getOp(), ctx.getReferringVertex(), ctx.getAttribute(), newElements.get(index), - ctx.getVertexProperty(), elementType, existingEdge); + if (cardinality == SET) { + newElements = (List) newElements.stream().distinct().collect(Collectors.toList()); + } - Object newEntry = mapCollectionElementsToVertex(arrCtx, context); + for (int index = 0; index < newElements.size(); index++) { + AtlasEdge existingEdge = (isSoftReference) ? null : getEdgeAt(currentElements, index, elementType); + AttributeMutationContext arrCtx = new AttributeMutationContext(ctx.getOp(), ctx.getReferringVertex(), ctx.getAttribute(), newElements.get(index), + ctx.getVertexProperty(), elementType, existingEdge); - if (isReference && newEntry != null && newEntry instanceof AtlasEdge && inverseRefAttribute != null) { - // Update the inverse reference value. - AtlasEdge newEdge = (AtlasEdge) newEntry; + Object newEntry = mapCollectionElementsToVertex(arrCtx, context); - addInverseReference(context, inverseRefAttribute, newEdge, getRelationshipAttributes(ctx.getValue())); - } + if (isReference && newEntry != null && newEntry instanceof AtlasEdge && inverseRefAttribute != null) { + // Update the inverse reference value. + AtlasEdge newEdge = (AtlasEdge) newEntry; - if(newEntry != null) { - newElementsCreated.add(newEntry); - } + addInverseReference(context, inverseRefAttribute, newEdge, getRelationshipAttributes(ctx.getValue())); + } + + if(newEntry != null) { + newElementsCreated.add(newEntry); } } @@ -1065,8 +1079,11 @@ public class EntityGraphMapper { } } - // for dereference on way out - setArrayElementsProperty(elementType, isSoftReference, ctx.getReferringVertex(), ctx.getVertexProperty(), newElementsCreated); + if (isNewElementsNull) { + setArrayElementsProperty(elementType, isSoftReference, ctx.getReferringVertex(), ctx.getVertexProperty(), null); + } else { + setArrayElementsProperty(elementType, isSoftReference, ctx.getReferringVertex(), ctx.getVertexProperty(), newElementsCreated); + } if (LOG.isDebugEnabled()) { LOG.debug("<== mapArrayValue({})", ctx); diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java index 9f77d67..4bfb4ee 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java @@ -74,6 +74,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -740,7 +741,9 @@ public class EntityGraphRetriever { Map<String, AtlasObjectId> ret = null; Map softRefVal = entityVertex.getProperty(attribute.getVertexPropertyName(), Map.class); - if (MapUtils.isNotEmpty(softRefVal)) { + if (MapUtils.isEmpty(softRefVal)) { + return softRefVal; + } else { ret = new HashMap<>(); for (Object mapKey : softRefVal.keySet()) { @@ -751,7 +754,6 @@ public class EntityGraphRetriever { } } } - return ret; } @@ -759,7 +761,9 @@ public class EntityGraphRetriever { List<AtlasObjectId> ret = null; List softRefVal = entityVertex.getListProperty(attribute.getVertexPropertyName(), List.class); - if (CollectionUtils.isNotEmpty(softRefVal)) { + if (CollectionUtils.isEmpty(softRefVal)) { + return softRefVal; + } else { ret = new ArrayList<>(); for (Object o : softRefVal) { @@ -841,10 +845,6 @@ public class EntityGraphRetriever { ret = getPrimitiveMap(entityVertex, attribute.getVertexPropertyName()); } - if (MapUtils.isEmpty(ret)) { - ret = null; - } - return ret; } @@ -855,14 +855,14 @@ public class EntityGraphRetriever { AtlasType arrayElementType = arrayType.getElementType(); List<Object> arrayElements = getArrayElementsProperty(arrayElementType, entityVertex, attribute); - if (CollectionUtils.isEmpty(arrayElements)) { - return null; - } - if (LOG.isDebugEnabled()) { LOG.debug("Mapping array attribute {} for vertex {}", arrayElementType.getTypeName(), entityVertex); } + if (CollectionUtils.isEmpty(arrayElements)) { + return arrayElements; + } + List arrValues = new ArrayList(arrayElements.size()); String edgeLabel = attribute.getRelationshipEdgeLabel(); AtlasRelationshipEdgeDirection edgeDirection = attribute.getRelationshipEdgeDirection(); diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasComplexAttributesTest.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasComplexAttributesTest.java index cf7fa08..b95c067 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasComplexAttributesTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasComplexAttributesTest.java @@ -38,6 +38,7 @@ import org.testng.annotations.Test; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -48,6 +49,7 @@ import static org.apache.atlas.TestUtilsV2.ENTITY_TYPE; import static org.apache.atlas.TestUtilsV2.ENTITY_TYPE_MAP; import static org.apache.atlas.TestUtilsV2.ENTITY_TYPE_WITH_COMPLEX_COLLECTION_ATTR; import static org.apache.atlas.TestUtilsV2.ENTITY_TYPE_WITH_COMPLEX_COLLECTION_ATTR_DELETE; +import static org.apache.atlas.TestUtilsV2.ENTITY_TYPE_WITH_SIMPLE_ATTR; import static org.apache.atlas.TestUtilsV2.NAME; import static org.apache.atlas.repository.graph.GraphHelper.getStatus; import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId; @@ -66,7 +68,8 @@ public class AtlasComplexAttributesTest extends AtlasEntityTestBase { // create typeDefs AtlasTypesDef[] testTypesDefs = new AtlasTypesDef[] { TestUtilsV2.defineTypeWithComplexCollectionAttributes(), - TestUtilsV2.defineTypeWithMapAttributes() }; + TestUtilsV2.defineTypeWithMapAttributes(), + TestUtilsV2.defineSimpleAttrType()}; createTypesDef(testTypesDefs); // create entity @@ -195,6 +198,51 @@ public class AtlasComplexAttributesTest extends AtlasEntityTestBase { attrEntity.setAttribute("mapAttr5", map5); } + @Test + public void testArrayAttribute() throws Exception { + init(); + + AtlasEntityWithExtInfo simpleEntity = TestUtilsV2.createSimpleAttrTypeEntity(); + EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(simpleEntity), false); + AtlasEntityHeader simpleEntityHeader = response.getFirstCreatedEntityByTypeName(ENTITY_TYPE_WITH_SIMPLE_ATTR); + AtlasEntity createdSimpleEntity = getEntityFromStore(simpleEntityHeader); + + validateEntity(simpleEntity, createdSimpleEntity); + + createdSimpleEntity.setAttribute("stringAtrr", null); + createdSimpleEntity.setAttribute("mapOfStrings", Collections.emptyMap()); + createdSimpleEntity.setAttribute("arrayOfStrings", Collections.emptyList()); + EntityMutationResponse responseUpdated = entityStore.createOrUpdate(new AtlasEntityStream(createdSimpleEntity), false); + AtlasEntityHeader simpleEntityUpdatedHeader = responseUpdated.getFirstUpdatedEntityByTypeName(ENTITY_TYPE_WITH_SIMPLE_ATTR); + AtlasEntity updatedSimpleEntity = getEntityFromStore(simpleEntityUpdatedHeader); + + assertNull(updatedSimpleEntity.getAttribute("stringAtrr")); + assertEquals(updatedSimpleEntity.getAttribute("mapOfStrings"), Collections.emptyMap()); + assertEquals(updatedSimpleEntity.getAttribute("arrayOfStrings"), Collections.emptyList()); + + updatedSimpleEntity.setAttribute("stringAtrr", ""); + updatedSimpleEntity.setAttribute("mapOfStrings", null); + updatedSimpleEntity.setAttribute("arrayOfStrings", null); + EntityMutationResponse responseUpdatedAgain = entityStore.createOrUpdate(new AtlasEntityStream(updatedSimpleEntity), false); + AtlasEntityHeader simpleEntityUpdatedAgainHeader = responseUpdatedAgain.getFirstUpdatedEntityByTypeName(ENTITY_TYPE_WITH_SIMPLE_ATTR); + AtlasEntity updatedAgainSimpleEntity = getEntityFromStore(simpleEntityUpdatedAgainHeader); + + assertEquals(updatedAgainSimpleEntity.getAttribute("stringAtrr"), ""); + assertNull(updatedAgainSimpleEntity.getAttribute("arrayOfStrings")); + assertNull(updatedAgainSimpleEntity.getAttribute("mapOfStrings")); + + updatedAgainSimpleEntity.setAttribute("stringAtrr", "Dummy String Test 3"); + updatedAgainSimpleEntity.setAttribute("mapOfStrings", Collections.singletonMap("key1", "val1")); + updatedAgainSimpleEntity.setAttribute("arrayOfStrings", Arrays.asList("DummyTest3", "DummyTest4")); + EntityMutationResponse updateRes = entityStore.createOrUpdate(new AtlasEntityStream(updatedAgainSimpleEntity), false); + AtlasEntityHeader updateHeader = updateRes.getFirstUpdatedEntityByTypeName(ENTITY_TYPE_WITH_SIMPLE_ATTR); + AtlasEntity updateEntity = getEntityFromStore(updateHeader); + + assertEquals(updateEntity.getAttribute("stringAtrr"), "Dummy String Test 3"); + assertEquals(updateEntity.getAttribute("arrayOfStrings"), Arrays.asList("DummyTest3", "DummyTest4")); + assertEquals(updateEntity.getAttribute("mapOfStrings"), Collections.singletonMap("key1", "val1")); + } + @Test(dependsOnMethods = "testCreateComplexAttributeEntity") public void testStructArray() throws Exception { init();