2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.deutschebahn.internal.filter;
15 import static org.hamcrest.MatcherAssert.assertThat;
16 import static org.hamcrest.Matchers.*;
17 import static org.junit.jupiter.api.Assertions.fail;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.regex.Pattern;
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.junit.jupiter.api.Test;
27 import org.openhab.binding.deutschebahn.internal.AttributeSelection;
28 import org.openhab.binding.deutschebahn.internal.EventAttribute;
29 import org.openhab.binding.deutschebahn.internal.EventAttributeSelection;
30 import org.openhab.binding.deutschebahn.internal.EventType;
31 import org.openhab.binding.deutschebahn.internal.TripLabelAttribute;
34 * Tests for {@link FilterParser}
36 * @author Sönke Küper - Initial contribution.
39 public class FilterParserTest {
41 private static final class FilterTokenSequenceBuilder {
43 private final List<FilterToken> tokens = new ArrayList<>();
44 private int position = 0;
46 private int getPos() {
51 public List<FilterToken> build() {
55 public FilterTokenSequenceBuilder and() {
56 this.tokens.add(new AndOperator(getPos()));
60 public FilterTokenSequenceBuilder or() {
61 this.tokens.add(new OrOperator(getPos()));
65 public FilterTokenSequenceBuilder bracketOpen() {
66 this.tokens.add(new BracketOpenToken(getPos()));
70 public FilterTokenSequenceBuilder bracketClose() {
71 this.tokens.add(new BracketCloseToken(getPos()));
75 public ChannelNameEquals channelFilter(String channelGroup, String channelName, String pattern) {
76 ChannelNameEquals channelNameEquals = new ChannelNameEquals(getPos(), channelGroup, channelName,
77 Pattern.compile(pattern));
78 this.tokens.add(channelNameEquals);
79 return channelNameEquals;
82 public FilterTokenSequenceBuilder channelFilter(ChannelNameEquals equals) {
83 this.tokens.add(equals);
88 private static FilterTokenSequenceBuilder builder() {
89 return new FilterTokenSequenceBuilder();
92 private static void checkAttributeFilter(TimetableStopPredicate predicate, ChannelNameEquals channelEquals,
93 EventType eventType, EventAttribute<?, ?> eventAttribute) {
94 checkAttributeFilter(predicate, channelEquals, new EventAttributeSelection(eventType, eventAttribute));
97 private static void checkAttributeFilter(TimetableStopPredicate predicate, ChannelNameEquals channelEquals,
98 AttributeSelection attributeSelection) {
99 assertThat(predicate, is(instanceOf(TimetableStopByStringEventAttributeFilter.class)));
100 TimetableStopByStringEventAttributeFilter attributeFilter = (TimetableStopByStringEventAttributeFilter) predicate;
101 assertThat(attributeFilter.getFilter(), is(channelEquals.getFilterValue()));
102 assertThat(attributeFilter.getAttributeSelection(), is(attributeSelection));
105 private static OrPredicate assertOr(TimetableStopPredicate predicate) {
106 assertThat(predicate, is(instanceOf(OrPredicate.class)));
107 return (OrPredicate) predicate;
110 private static AndPredicate assertAnd(TimetableStopPredicate predicate) {
111 assertThat(predicate, is(instanceOf(AndPredicate.class)));
112 return (AndPredicate) predicate;
116 public void testParseSimple() throws FilterParserException {
117 final List<FilterToken> input = new ArrayList<>();
118 ChannelNameEquals channelEquals = new ChannelNameEquals(1, "trip", "number", Pattern.compile("20"));
119 input.add(channelEquals);
120 final TimetableStopPredicate result = FilterParser.parse(input);
121 checkAttributeFilter(result, channelEquals, TripLabelAttribute.N);
125 public void testParseAnd() throws FilterParserException {
126 final FilterTokenSequenceBuilder b = builder();
127 final ChannelNameEquals channelEquals01 = b.channelFilter("trip", "number", "20");
129 final ChannelNameEquals channelEquals02 = b.channelFilter("trip", "number", "30");
130 final TimetableStopPredicate result = FilterParser.parse(b.build());
131 final AndPredicate andPredicate = assertAnd(result);
133 checkAttributeFilter(andPredicate.getFirst(), channelEquals01, TripLabelAttribute.N);
134 checkAttributeFilter(andPredicate.getSecond(), channelEquals02, TripLabelAttribute.N);
138 public void testParseOr() throws FilterParserException {
139 final FilterTokenSequenceBuilder b = builder();
140 final ChannelNameEquals channelEquals01 = b.channelFilter("trip", "number", "20");
142 final ChannelNameEquals channelEquals02 = b.channelFilter("trip", "number", "30");
143 final TimetableStopPredicate result = FilterParser.parse(b.build());
144 final OrPredicate orPredicate = assertOr(result);
146 checkAttributeFilter(orPredicate.getFirst(), channelEquals01, TripLabelAttribute.N);
147 checkAttributeFilter(orPredicate.getSecond(), channelEquals02, TripLabelAttribute.N);
151 public void testParseWithBrackets() throws FilterParserException {
152 final FilterTokenSequenceBuilder b = new FilterTokenSequenceBuilder();
153 final ChannelNameEquals channelEquals01 = b.channelFilter("trip", "number", "20");
156 final ChannelNameEquals channelEquals02 = b.channelFilter("departure", "line", "RE10");
158 final ChannelNameEquals channelEquals03 = b.channelFilter("departure", "line", "RE20");
160 final List<FilterToken> input = b.build();
162 final TimetableStopPredicate result = FilterParser.parse(input);
163 final AndPredicate andPredicate = assertAnd(result);
165 checkAttributeFilter(andPredicate.getFirst(), channelEquals01, TripLabelAttribute.N);
166 final OrPredicate orPredicate = assertOr(andPredicate.getSecond());
168 checkAttributeFilter(orPredicate.getFirst(), channelEquals02, EventType.DEPARTURE, EventAttribute.L);
169 checkAttributeFilter(orPredicate.getSecond(), channelEquals03, EventType.DEPARTURE, EventAttribute.L);
173 public void testParseWithMultipleBrackets() throws FilterParserException {
174 final FilterTokenSequenceBuilder b = builder();
177 final ChannelNameEquals channelEquals01 = b.channelFilter("trip", "number", "20");
179 final ChannelNameEquals channelEquals02 = b.channelFilter("departure", "line", "RE22");
183 final ChannelNameEquals channelEquals03 = b.channelFilter("trip", "number", "30");
185 final ChannelNameEquals channelEquals04 = b.channelFilter("departure", "line", "RE33");
189 final List<FilterToken> input = b.build();
191 final TimetableStopPredicate result = FilterParser.parse(input);
192 final OrPredicate orPredicate = assertOr(result);
194 final AndPredicate firstAnd = assertAnd(orPredicate.getFirst());
195 checkAttributeFilter(firstAnd.getFirst(), channelEquals01, TripLabelAttribute.N);
196 checkAttributeFilter(firstAnd.getSecond(), channelEquals02, EventType.DEPARTURE, EventAttribute.L);
198 final AndPredicate secondAnd = assertAnd(orPredicate.getSecond());
199 checkAttributeFilter(secondAnd.getFirst(), channelEquals03, TripLabelAttribute.N);
200 checkAttributeFilter(secondAnd.getSecond(), channelEquals04, EventType.DEPARTURE, EventAttribute.L);
204 public void testParseErrors() {
205 final ChannelNameEquals channelEquals = new ChannelNameEquals(1, "trip", "number", Pattern.compile("20"));
207 FilterParser.parse(Collections.emptyList());
209 } catch (FilterParserException e) {
213 FilterParser.parse(builder().and().build());
215 } catch (FilterParserException e) {
219 FilterParser.parse(builder().or().build());
221 } catch (FilterParserException e) {
224 FilterParser.parse(builder().bracketOpen().build());
226 } catch (FilterParserException e) {
229 FilterParser.parse(builder().bracketClose().build());
231 } catch (FilterParserException e) {
234 FilterParser.parse(builder().bracketOpen().bracketClose().build());
236 } catch (FilterParserException e) {
239 FilterParser.parse(builder().bracketOpen().and().build());
241 } catch (FilterParserException e) {
244 FilterParser.parse(builder().bracketOpen().and().build());
246 } catch (FilterParserException e) {
249 FilterParser.parse(builder().channelFilter(channelEquals).and().bracketOpen().build());
251 } catch (FilterParserException e) {
254 FilterParser.parse(builder().channelFilter(channelEquals).and().bracketClose().build());
256 } catch (FilterParserException e) {
259 FilterParser.parse(builder().channelFilter(channelEquals).or().bracketOpen().build());
261 } catch (FilterParserException e) {
264 FilterParser.parse(builder().channelFilter(channelEquals).or().bracketClose().build());
266 } catch (FilterParserException e) {
269 FilterParser.parse(builder().channelFilter(channelEquals).and().build());
271 } catch (FilterParserException e) {
274 FilterParser.parse(builder().channelFilter(channelEquals).or().build());
276 } catch (FilterParserException e) {
279 FilterParser.parse(Arrays.asList(channelEquals, channelEquals));
281 } catch (FilterParserException e) {