mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-25 17:04:54 +00:00
updated rule evealutor tests (#9711)
* updated rule evealutor tests * Update - review comments
This commit is contained in:
parent
c3197beaf4
commit
bbfb50f298
@ -51,12 +51,12 @@ public class AlertsRuleEvaluator {
|
||||
description = "Returns true if the change event entity being accessed has source as mentioned in condition",
|
||||
examples = {"matchAnySource('bot', 'user')"},
|
||||
paramInputType = READ_FROM_PARAM_CONTEXT)
|
||||
public boolean matchAnySource(String... originEntity) {
|
||||
if (changeEvent == null) {
|
||||
public boolean matchAnySource(String... originEntities) {
|
||||
if (changeEvent == null || changeEvent.getEntityType() == null) {
|
||||
return false;
|
||||
}
|
||||
String changeEventEntity = changeEvent.getEntityType();
|
||||
for (String entityType : originEntity) {
|
||||
for (String entityType : originEntities) {
|
||||
if (changeEventEntity.equals(entityType)) {
|
||||
return true;
|
||||
}
|
||||
@ -74,14 +74,7 @@ public class AlertsRuleEvaluator {
|
||||
if (changeEvent == null || changeEvent.getEntity() == null) {
|
||||
return false;
|
||||
}
|
||||
Class<? extends EntityInterface> entityClass = Entity.getEntityClassFromType(changeEvent.getEntityType());
|
||||
EntityInterface entity;
|
||||
if (changeEvent.getEntity() instanceof String) {
|
||||
entity = JsonUtils.readValue((String) changeEvent.getEntity(), entityClass);
|
||||
} else {
|
||||
entity = JsonUtils.convertValue(changeEvent.getEntity(), entityClass);
|
||||
}
|
||||
|
||||
EntityInterface entity = getEntity(changeEvent);
|
||||
EntityReference ownerReference = entity.getOwner();
|
||||
if (ownerReference != null) {
|
||||
if (USER.equals(ownerReference.getType())) {
|
||||
@ -109,11 +102,11 @@ public class AlertsRuleEvaluator {
|
||||
description = "Returns true if the change event entity being accessed has following entityName from the List.",
|
||||
examples = {"matchAnyEntityFqn('Name1', 'Name')"},
|
||||
paramInputType = ALL_INDEX_ELASTIC_SEARCH)
|
||||
public boolean matchAnyEntityFqn(String... entityNames) {
|
||||
public boolean matchAnyEntityFqn(String... entityNames) throws IOException {
|
||||
if (changeEvent == null || changeEvent.getEntity() == null) {
|
||||
return false;
|
||||
}
|
||||
EntityInterface entity = (EntityInterface) changeEvent.getEntity();
|
||||
EntityInterface entity = getEntity(changeEvent);
|
||||
for (String name : entityNames) {
|
||||
if (entity.getFullyQualifiedName().equals(name)) {
|
||||
return true;
|
||||
@ -128,11 +121,11 @@ public class AlertsRuleEvaluator {
|
||||
description = "Returns true if the change event entity being accessed has following entityId from the List.",
|
||||
examples = {"matchAnyEntityId('uuid1', 'uuid2')"},
|
||||
paramInputType = ALL_INDEX_ELASTIC_SEARCH)
|
||||
public boolean matchAnyEntityId(String... entityIds) {
|
||||
public boolean matchAnyEntityId(String... entityIds) throws IOException {
|
||||
if (changeEvent == null || changeEvent.getEntity() == null) {
|
||||
return false;
|
||||
}
|
||||
EntityInterface entity = (EntityInterface) changeEvent.getEntity();
|
||||
EntityInterface entity = getEntity(changeEvent);
|
||||
for (String id : entityIds) {
|
||||
if (entity.getId().equals(UUID.fromString(id))) {
|
||||
return true;
|
||||
@ -148,7 +141,7 @@ public class AlertsRuleEvaluator {
|
||||
examples = {"matchAnyEventType('entityCreated', 'entityUpdated', 'entityDeleted', 'entitySoftDeleted')"},
|
||||
paramInputType = READ_FROM_PARAM_CONTEXT)
|
||||
public boolean matchAnyEventType(String... eventTypesList) {
|
||||
if (changeEvent == null || changeEvent.getEntity() == null) {
|
||||
if (changeEvent == null || changeEvent.getEventType() == null) {
|
||||
return false;
|
||||
}
|
||||
String eventType = changeEvent.getEventType().toString();
|
||||
@ -167,7 +160,7 @@ public class AlertsRuleEvaluator {
|
||||
examples = {"matchTestResult('Success', 'Failed', 'Aborted')"},
|
||||
paramInputType = READ_FROM_PARAM_CONTEXT)
|
||||
public boolean matchTestResult(String... testResults) {
|
||||
if (changeEvent == null || changeEvent.getEntity() == null) {
|
||||
if (changeEvent == null || changeEvent.getChangeDescription() == null) {
|
||||
return false;
|
||||
}
|
||||
if (!changeEvent.getEntityType().equals(TEST_CASE)) {
|
||||
@ -195,7 +188,7 @@ public class AlertsRuleEvaluator {
|
||||
examples = {"matchUpdatedBy('user1', 'user2')"},
|
||||
paramInputType = READ_FROM_PARAM_CONTEXT)
|
||||
public boolean matchUpdatedBy(String... updatedByUserList) {
|
||||
if (changeEvent == null || changeEvent.getEntity() == null) {
|
||||
if (changeEvent == null || changeEvent.getUserName() == null) {
|
||||
return false;
|
||||
}
|
||||
String entityUpdatedBy = changeEvent.getUserName();
|
||||
@ -214,7 +207,7 @@ public class AlertsRuleEvaluator {
|
||||
examples = {"matchAnyFieldChange('fieldName1', 'fieldName')"},
|
||||
paramInputType = NOT_REQUIRED)
|
||||
public boolean matchAnyFieldChange(String... fieldChangeUpdate) {
|
||||
if (changeEvent == null || changeEvent.getEntity() == null) {
|
||||
if (changeEvent == null || changeEvent.getChangeDescription() == null) {
|
||||
return false;
|
||||
}
|
||||
Set<String> fields = ChangeEventParser.getUpdatedField(changeEvent);
|
||||
@ -225,4 +218,15 @@ public class AlertsRuleEvaluator {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private EntityInterface getEntity(ChangeEvent event) throws IOException {
|
||||
Class<? extends EntityInterface> entityClass = Entity.getEntityClassFromType(event.getEntityType());
|
||||
EntityInterface entity;
|
||||
if (event.getEntity() instanceof String) {
|
||||
entity = JsonUtils.readValue((String) event.getEntity(), entityClass);
|
||||
} else {
|
||||
entity = JsonUtils.convertValue(event.getEntity(), entityClass);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
@ -3,138 +3,180 @@ package org.openmetadata.service.alerts;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.openmetadata.service.security.policyevaluator.CompiledRule.parseExpression;
|
||||
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.openmetadata.schema.api.data.CreateTable;
|
||||
import org.openmetadata.schema.entity.data.Table;
|
||||
import org.openmetadata.schema.entity.teams.Team;
|
||||
import org.openmetadata.schema.entity.teams.User;
|
||||
import org.openmetadata.schema.tests.type.TestCaseResult;
|
||||
import org.openmetadata.schema.tests.type.TestCaseStatus;
|
||||
import org.openmetadata.schema.type.ChangeDescription;
|
||||
import org.openmetadata.schema.type.ChangeEvent;
|
||||
import org.openmetadata.schema.type.EntityReference;
|
||||
import org.openmetadata.schema.type.TagLabel;
|
||||
import org.openmetadata.schema.type.Column;
|
||||
import org.openmetadata.schema.type.ColumnDataType;
|
||||
import org.openmetadata.schema.type.EventType;
|
||||
import org.openmetadata.schema.type.FieldChange;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.jdbi3.CollectionDAO.TeamDAO;
|
||||
import org.openmetadata.service.jdbi3.CollectionDAO.UserDAO;
|
||||
import org.openmetadata.service.jdbi3.TableRepository;
|
||||
import org.openmetadata.service.jdbi3.TeamRepository;
|
||||
import org.openmetadata.service.jdbi3.UserRepository;
|
||||
import org.openmetadata.service.security.policyevaluator.ResourceContext;
|
||||
import org.openmetadata.service.OpenMetadataApplicationTest;
|
||||
import org.openmetadata.service.resources.EntityResourceTest;
|
||||
import org.openmetadata.service.resources.databases.TableResourceTest;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
class AlertsRuleEvaluatorTest {
|
||||
private static Table table;
|
||||
private static User user;
|
||||
private static EvaluationContext evaluationContext;
|
||||
class AlertsRuleEvaluatorTest extends OpenMetadataApplicationTest {
|
||||
private static TableResourceTest tableResourceTest;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() {
|
||||
Entity.registerEntity(User.class, Entity.USER, Mockito.mock(UserDAO.class), Mockito.mock(UserRepository.class));
|
||||
Entity.registerEntity(Team.class, Entity.TEAM, Mockito.mock(TeamDAO.class), Mockito.mock(TeamRepository.class));
|
||||
table = new Table().withName("table");
|
||||
user = new User().withId(UUID.randomUUID()).withName("user");
|
||||
ResourceContext resourceContext =
|
||||
ResourceContext.builder()
|
||||
.resource("table")
|
||||
.entity(table)
|
||||
.entityRepository(Mockito.mock(TableRepository.class))
|
||||
.build();
|
||||
// SubjectContext subjectContext = new SubjectContext(user);
|
||||
// RuleEvaluator ruleEvaluator = new RuleEvaluator(null, subjectContext, resourceContext);
|
||||
ChangeEvent event = new ChangeEvent();
|
||||
// evaluationContext = new StandardEvaluationContext(ruleEvaluator);
|
||||
public static void setup(TestInfo test) throws URISyntaxException, IOException {
|
||||
tableResourceTest = new TableResourceTest();
|
||||
tableResourceTest.setup(test);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_noOwner() {
|
||||
// Set no owner to the entity and test noOwner method
|
||||
table.setOwner(null);
|
||||
assertTrue(evaluateExpression("noOwner()"));
|
||||
assertFalse(evaluateExpression("!noOwner()"));
|
||||
|
||||
// Set owner to the entity and test noOwner method
|
||||
table.setOwner(new EntityReference().withId(UUID.randomUUID()).withType(Entity.USER));
|
||||
assertFalse(evaluateExpression("noOwner()"));
|
||||
assertTrue(evaluateExpression("!noOwner()"));
|
||||
void test_matchAnySource() {
|
||||
// Create a change Event with Entity Type and test for source in list and not in list
|
||||
ChangeEvent changeEvent = new ChangeEvent();
|
||||
changeEvent.setEntityType("alert");
|
||||
AlertsRuleEvaluator alertsRuleEvaluator = new AlertsRuleEvaluator(changeEvent);
|
||||
EvaluationContext evaluationContext = new StandardEvaluationContext(alertsRuleEvaluator);
|
||||
assertTrue(evaluateExpression("matchAnySource('alert')", evaluationContext));
|
||||
assertFalse(evaluateExpression("matchAnySource('bot')", evaluationContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_isOwner() {
|
||||
// Table owner is a different user (random ID) and hence isOwner returns false
|
||||
table.setOwner(new EntityReference().withId(UUID.randomUUID()).withType(Entity.USER).withName("otherUser"));
|
||||
assertFalse(evaluateExpression("isOwner()"));
|
||||
assertTrue(evaluateExpression("!isOwner()"));
|
||||
void test_matchAnyOwnerName(TestInfo test) throws IOException {
|
||||
// Create Table Entity
|
||||
List<Column> columns = List.of(TableResourceTest.getColumn("c1", ColumnDataType.INT, null));
|
||||
CreateTable create =
|
||||
tableResourceTest.createRequest(test).withColumns(columns).withOwner(EntityResourceTest.USER1_REF);
|
||||
Table createdTable = tableResourceTest.createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
|
||||
|
||||
// Table owner is same as the user in subjectContext and hence isOwner returns true
|
||||
table.setOwner(new EntityReference().withId(user.getId()).withType(Entity.USER).withName(user.getName()));
|
||||
assertTrue(evaluateExpression("isOwner()"));
|
||||
assertFalse(evaluateExpression("!isOwner()"));
|
||||
// Create a change Event with the Entity Table
|
||||
ChangeEvent changeEvent = new ChangeEvent();
|
||||
changeEvent.setEntityType(Entity.TABLE);
|
||||
changeEvent.setEntity(createdTable);
|
||||
|
||||
// noOwner() || isOwner() - with noOwner being true and isOwner false
|
||||
table.setOwner(null);
|
||||
assertTrue(evaluateExpression("noOwner() || isOwner()"));
|
||||
assertFalse(evaluateExpression("!noOwner() && !isOwner()"));
|
||||
|
||||
// noOwner() || isOwner() - with noOwner is false and isOwner true
|
||||
table.setOwner(new EntityReference().withId(user.getId()).withType(Entity.USER).withName(user.getName()));
|
||||
assertTrue(evaluateExpression("noOwner() || isOwner()"));
|
||||
assertFalse(evaluateExpression("!noOwner() && !isOwner()"));
|
||||
// Test Owner Name Present in list and not present in list
|
||||
AlertsRuleEvaluator alertsRuleEvaluator = new AlertsRuleEvaluator(changeEvent);
|
||||
EvaluationContext evaluationContext = new StandardEvaluationContext(alertsRuleEvaluator);
|
||||
assertTrue(
|
||||
evaluateExpression("matchAnyOwnerName('" + EntityResourceTest.USER1.getName() + "')", evaluationContext));
|
||||
assertFalse(evaluateExpression("matchAnyOwnerName('tempName')", evaluationContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_matchAllTags() {
|
||||
table.withTags(getTags("tag1", "tag2", "tag3"));
|
||||
void test_matchAnyEntityFqn(TestInfo test) throws IOException {
|
||||
// Create Table Entity
|
||||
List<Column> columns = List.of(TableResourceTest.getColumn("c1", ColumnDataType.INT, null));
|
||||
CreateTable create = tableResourceTest.createRequest(test).withColumns(columns);
|
||||
Table createdTable = tableResourceTest.createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
|
||||
|
||||
// All tags present
|
||||
assertTrue(evaluateExpression("matchAllTags('tag1', 'tag2', 'tag3')"));
|
||||
assertFalse(evaluateExpression("!matchAllTags('tag1', 'tag2', 'tag3')"));
|
||||
assertTrue(evaluateExpression("matchAllTags('tag1', 'tag2')"));
|
||||
assertFalse(evaluateExpression("!matchAllTags('tag1', 'tag2')"));
|
||||
assertTrue(evaluateExpression("matchAllTags('tag1')"));
|
||||
assertFalse(evaluateExpression("!matchAllTags('tag1')"));
|
||||
// Create a change Event with the Entity Table
|
||||
ChangeEvent changeEvent = new ChangeEvent();
|
||||
changeEvent.setEntityType(Entity.TABLE);
|
||||
changeEvent.setEntity(createdTable);
|
||||
|
||||
// Tag 'tag4' is missing
|
||||
assertFalse(evaluateExpression("matchAllTags('tag1', 'tag2', 'tag3', 'tag4')"));
|
||||
assertTrue(evaluateExpression("!matchAllTags('tag1', 'tag2', 'tag3', 'tag4')"));
|
||||
assertFalse(evaluateExpression("matchAllTags('tag1', 'tag2', 'tag4')"));
|
||||
assertTrue(evaluateExpression("!matchAllTags('tag1', 'tag2', 'tag4')"));
|
||||
assertFalse(evaluateExpression("matchAllTags('tag2', 'tag4')"));
|
||||
assertTrue(evaluateExpression("!matchAllTags('tag2', 'tag4')"));
|
||||
assertFalse(evaluateExpression("matchAllTags('tag4')"));
|
||||
assertTrue(evaluateExpression("!matchAllTags('tag4')"));
|
||||
// Test Entity Fqn in List of match and not present in list
|
||||
AlertsRuleEvaluator alertsRuleEvaluator = new AlertsRuleEvaluator(changeEvent);
|
||||
EvaluationContext evaluationContext = new StandardEvaluationContext(alertsRuleEvaluator);
|
||||
String fqn = createdTable.getFullyQualifiedName();
|
||||
assertTrue(evaluateExpression("matchAnyEntityFqn('" + fqn + "')", evaluationContext));
|
||||
assertFalse(evaluateExpression("matchAnyEntityFqn('testFQN1')", evaluationContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_matchAnyTag() {
|
||||
table.withTags(getTags("tag1", "tag2", "tag3"));
|
||||
void test_matchAnyEntityId(TestInfo test) throws IOException {
|
||||
// Create Table Entity
|
||||
List<Column> columns = List.of(TableResourceTest.getColumn("c1", ColumnDataType.INT, null));
|
||||
CreateTable create = tableResourceTest.createRequest(test).withColumns(columns);
|
||||
Table createdTable = tableResourceTest.createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
|
||||
|
||||
// Tag is present
|
||||
assertTrue(evaluateExpression("matchAnyTag('tag1', 'tag2', 'tag3', 'tag4')"));
|
||||
assertFalse(evaluateExpression("!matchAnyTag('tag1', 'tag2', 'tag3', 'tag4')"));
|
||||
assertTrue(evaluateExpression("matchAnyTag('tag1', 'tag2', 'tag4')"));
|
||||
assertFalse(evaluateExpression("!matchAnyTag('tag1', 'tag2', 'tag4')"));
|
||||
assertTrue(evaluateExpression("matchAnyTag('tag1', 'tag2', 'tag4')"));
|
||||
assertFalse(evaluateExpression("!matchAnyTag('tag1', 'tag2', 'tag4')"));
|
||||
assertTrue(evaluateExpression("matchAnyTag('tag1', 'tag4')"));
|
||||
assertFalse(evaluateExpression("!matchAnyTag('tag1', 'tag4')"));
|
||||
// Create a change Event with Table Entity and Type
|
||||
ChangeEvent changeEvent = new ChangeEvent();
|
||||
changeEvent.setEntityType(Entity.TABLE);
|
||||
changeEvent.setEntity(createdTable);
|
||||
|
||||
// Tag `tag4` is not present
|
||||
assertFalse(evaluateExpression("matchAnyTag('tag4')"));
|
||||
assertTrue(evaluateExpression("!matchAnyTag('tag4')"));
|
||||
// Test Entity Id in List of match and not present in list
|
||||
AlertsRuleEvaluator alertsRuleEvaluator = new AlertsRuleEvaluator(changeEvent);
|
||||
EvaluationContext evaluationContext = new StandardEvaluationContext(alertsRuleEvaluator);
|
||||
String id = createdTable.getId().toString();
|
||||
assertTrue(evaluateExpression("matchAnyEntityId('" + id + "')", evaluationContext));
|
||||
assertFalse(evaluateExpression("matchAnyEntityId('" + UUID.randomUUID() + "')", evaluationContext));
|
||||
}
|
||||
|
||||
private Boolean evaluateExpression(String condition) {
|
||||
@Test
|
||||
void test_matchAnyEventType() {
|
||||
// Create a change Event with EventType
|
||||
ChangeEvent changeEvent = new ChangeEvent();
|
||||
changeEvent.setEventType(EventType.ENTITY_CREATED);
|
||||
|
||||
// Check if eventType present in list or absent from the list
|
||||
AlertsRuleEvaluator alertsRuleEvaluator = new AlertsRuleEvaluator(changeEvent);
|
||||
EvaluationContext evaluationContext = new StandardEvaluationContext(alertsRuleEvaluator);
|
||||
assertTrue(evaluateExpression("matchAnyEventType('entityCreated')", evaluationContext));
|
||||
assertFalse(evaluateExpression("matchAnyEventType('entityUpdated')", evaluationContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_matchTestResult() {
|
||||
// Create a change Description with Test Result Field
|
||||
ChangeDescription changeDescription = new ChangeDescription();
|
||||
changeDescription.setFieldsUpdated(
|
||||
List.of(
|
||||
new FieldChange()
|
||||
.withName("testCaseResult")
|
||||
.withOldValue("test1")
|
||||
.withNewValue(new TestCaseResult().withTestCaseStatus(TestCaseStatus.Success))));
|
||||
|
||||
// Create a change event with Test Case and Test Result Change Description
|
||||
ChangeEvent changeEvent = new ChangeEvent();
|
||||
changeEvent.setEntityType(Entity.TEST_CASE);
|
||||
changeEvent.setChangeDescription(changeDescription);
|
||||
|
||||
// Test If Test Result status matches in list and if status not matches
|
||||
AlertsRuleEvaluator alertsRuleEvaluator = new AlertsRuleEvaluator(changeEvent);
|
||||
EvaluationContext evaluationContext = new StandardEvaluationContext(alertsRuleEvaluator);
|
||||
assertTrue(evaluateExpression("matchTestResult('Success')", evaluationContext));
|
||||
assertFalse(evaluateExpression("matchTestResult('Failed')", evaluationContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_matchUpdatedBy() {
|
||||
// Create a change Event with updatedBy username
|
||||
ChangeEvent changeEvent = new ChangeEvent();
|
||||
changeEvent.setUserName("test");
|
||||
|
||||
// Test if the username is in list or not
|
||||
AlertsRuleEvaluator alertsRuleEvaluator = new AlertsRuleEvaluator(changeEvent);
|
||||
EvaluationContext evaluationContext = new StandardEvaluationContext(alertsRuleEvaluator);
|
||||
assertTrue(evaluateExpression("matchUpdatedBy('test')", evaluationContext));
|
||||
assertFalse(evaluateExpression("matchUpdatedBy('test1')", evaluationContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_matchAnyFieldChange() {
|
||||
// Create a change Event with some Change Description and Field Change
|
||||
ChangeDescription changeDescription = new ChangeDescription();
|
||||
changeDescription.setFieldsUpdated(
|
||||
List.of(new FieldChange().withName("test").withOldValue("test1").withNewValue("test2")));
|
||||
|
||||
ChangeEvent changeEvent = new ChangeEvent();
|
||||
changeEvent.setChangeDescription(changeDescription);
|
||||
|
||||
// Test if the updated field matches from the list or not
|
||||
AlertsRuleEvaluator alertsRuleEvaluator = new AlertsRuleEvaluator(changeEvent);
|
||||
EvaluationContext evaluationContext = new StandardEvaluationContext(alertsRuleEvaluator);
|
||||
assertTrue(evaluateExpression("matchAnyFieldChange('test')", evaluationContext));
|
||||
assertFalse(evaluateExpression("matchAnyFieldChange('temp')", evaluationContext));
|
||||
}
|
||||
|
||||
private Boolean evaluateExpression(String condition, EvaluationContext evaluationContext) {
|
||||
return parseExpression(condition).getValue(evaluationContext, Boolean.class);
|
||||
}
|
||||
|
||||
private List<TagLabel> getTags(String... tags) {
|
||||
List<TagLabel> tagLabels = new ArrayList<>();
|
||||
for (String tag : tags) {
|
||||
tagLabels.add(new TagLabel().withTagFQN(tag));
|
||||
}
|
||||
return tagLabels;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user