Fix "recursive membership detected" for plain items (#2918)

Signed-off-by: Jan N. Klug <github@klug.nrw>
pull/2894/head
J-N-K 2022-04-24 14:38:41 +02:00 committed by GitHub
parent ca94fd57b0
commit a42e798c8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 6 deletions

View File

@ -41,6 +41,12 @@
<version>${project.version}</version> <version>${project.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -64,16 +64,19 @@ public class EnrichedItemDTOMapper {
return map(item, itemDTO, drillDown, itemFilter, uriBuilder, locale, new ArrayList<>()); return map(item, itemDTO, drillDown, itemFilter, uriBuilder, locale, new ArrayList<>());
} }
private static EnrichedItemDTO map(Item item, boolean drillDown, @Nullable Predicate<Item> itemFilter, private static EnrichedItemDTO mapRecursive(Item item, @Nullable Predicate<Item> itemFilter,
@Nullable UriBuilder uriBuilder, @Nullable Locale locale, List<Item> parents) { @Nullable UriBuilder uriBuilder, @Nullable Locale locale, List<Item> parents) {
ItemDTO itemDTO = ItemDTOMapper.map(item); ItemDTO itemDTO = ItemDTOMapper.map(item);
return map(item, itemDTO, drillDown, itemFilter, uriBuilder, locale, parents); return map(item, itemDTO, true, itemFilter, uriBuilder, locale, parents);
} }
private static EnrichedItemDTO map(Item item, ItemDTO itemDTO, boolean drillDown, private static EnrichedItemDTO map(Item item, ItemDTO itemDTO, boolean drillDown,
@Nullable Predicate<Item> itemFilter, @Nullable UriBuilder uriBuilder, @Nullable Locale locale, @Nullable Predicate<Item> itemFilter, @Nullable UriBuilder uriBuilder, @Nullable Locale locale,
List<Item> parents) { List<Item> parents) {
parents.add(item); if (item instanceof GroupItem) {
// only add as parent item if it is a group, otherwise duplicate memberships trigger false warnings
parents.add(item);
}
String state = item.getState().toFullString(); String state = item.getState().toFullString();
String transformedState = considerTransformation(state, item, locale); String transformedState = considerTransformation(state, item, locale);
if (transformedState != null && transformedState.equals(state)) { if (transformedState != null && transformedState.equals(state)) {
@ -88,7 +91,7 @@ public class EnrichedItemDTOMapper {
link = null; link = null;
} }
EnrichedItemDTO enrichedItemDTO = null; EnrichedItemDTO enrichedItemDTO;
if (item instanceof GroupItem) { if (item instanceof GroupItem) {
GroupItem groupItem = (GroupItem) item; GroupItem groupItem = (GroupItem) item;
@ -101,10 +104,10 @@ public class EnrichedItemDTOMapper {
"Recursive group membership found: {} is both, a direct or indirect parent and a child of {}.", "Recursive group membership found: {} is both, a direct or indirect parent and a child of {}.",
member.getName(), groupItem.getName()); member.getName(), groupItem.getName());
} else if (itemFilter == null || itemFilter.test(member)) { } else if (itemFilter == null || itemFilter.test(member)) {
members.add(map(member, drillDown, itemFilter, uriBuilder, locale, parents)); members.add(mapRecursive(member, itemFilter, uriBuilder, locale, parents));
} }
} }
memberDTOs = members.toArray(new EnrichedItemDTO[members.size()]); memberDTOs = members.toArray(new EnrichedItemDTO[0]);
} else { } else {
memberDTOs = new EnrichedItemDTO[0]; memberDTOs = new EnrichedItemDTO[0];
} }

View File

@ -17,11 +17,20 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openhab.core.items.GenericItem; import org.openhab.core.items.GenericItem;
import org.openhab.core.items.GroupItem; import org.openhab.core.items.GroupItem;
import org.openhab.core.library.CoreItemFactory; import org.openhab.core.library.CoreItemFactory;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.test.java.JavaTest; import org.openhab.core.test.java.JavaTest;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
/** /**
* @author Kai Kreuzer - Initial contribution * @author Kai Kreuzer - Initial contribution
@ -29,6 +38,23 @@ import org.openhab.core.test.java.JavaTest;
@NonNullByDefault @NonNullByDefault
public class EnrichedItemDTOMapperTest extends JavaTest { public class EnrichedItemDTOMapperTest extends JavaTest {
private @NonNullByDefault({}) ListAppender<ILoggingEvent> listAppender;
@BeforeEach
public void setup() {
// add logging interceptor
Logger logger = (Logger) LoggerFactory.getLogger(EnrichedItemDTOMapper.class);
logger.setLevel(Level.ERROR);
listAppender = new ListAppender<>();
listAppender.start();
logger.addAppender(listAppender);
}
@AfterEach
public void tearDown() {
listAppender.stop();
}
@Test @Test
public void testFiltering() { public void testFiltering() {
CoreItemFactory itemFactory = new CoreItemFactory(); CoreItemFactory itemFactory = new CoreItemFactory();
@ -84,6 +110,12 @@ public class EnrichedItemDTOMapperTest extends JavaTest {
groupItem2.addMember(groupItem1); groupItem2.addMember(groupItem1);
assertDoesNotThrow(() -> EnrichedItemDTOMapper.map(groupItem1, true, null, null, null)); assertDoesNotThrow(() -> EnrichedItemDTOMapper.map(groupItem1, true, null, null, null));
assertThat(listAppender.list.size(), is(1));
ILoggingEvent loggingEvent = listAppender.list.get(0);
assertThat(loggingEvent.getLevel(), is(Level.ERROR));
assertThat(loggingEvent.getFormattedMessage(), is(
"Recursive group membership found: group1 is both, a direct or indirect parent and a child of group2."));
} }
@Test @Test
@ -97,5 +129,26 @@ public class EnrichedItemDTOMapperTest extends JavaTest {
groupItem3.addMember(groupItem1); groupItem3.addMember(groupItem1);
assertDoesNotThrow(() -> EnrichedItemDTOMapper.map(groupItem1, true, null, null, null)); assertDoesNotThrow(() -> EnrichedItemDTOMapper.map(groupItem1, true, null, null, null));
assertThat(listAppender.list.size(), is(1));
ILoggingEvent loggingEvent = listAppender.list.get(0);
assertThat(loggingEvent.getLevel(), is(Level.ERROR));
assertThat(loggingEvent.getFormattedMessage(), is(
"Recursive group membership found: group1 is both, a direct or indirect parent and a child of group3."));
}
@Test
public void testDuplicateMembershipOfPlainItemsDoesNotTriggerWarning() {
GroupItem groupItem1 = new GroupItem("group1");
GroupItem groupItem2 = new GroupItem("group2");
NumberItem numberItem = new NumberItem("number");
groupItem1.addMember(groupItem2);
groupItem1.addMember(numberItem);
groupItem2.addMember(numberItem);
EnrichedItemDTOMapper.map(groupItem1, true, null, null, null);
assertThat(listAppender.list.size(), is(0));
} }
} }