Add support for keyed entries
[mdsal.git] / dom / mdsal-dom-api / src / main / java / org / opendaylight / mdsal / dom / api / query / DOMQueryPredicate.java
1 /*
2  * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.dom.api.query;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.base.MoreObjects;
14 import com.google.common.base.MoreObjects.ToStringHelper;
15 import java.util.function.Predicate;
16 import java.util.regex.Pattern;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.yangtools.concepts.Immutable;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
23
24 @Beta
25 public abstract class DOMQueryPredicate implements Immutable, Predicate<NormalizedNode<?, ?>> {
26     abstract static class AbstractLeafDOMQueryPredicate extends DOMQueryPredicate {
27         AbstractLeafDOMQueryPredicate(final YangInstanceIdentifier relativePath) {
28             super(relativePath);
29         }
30
31         @Override
32         public final boolean test(final NormalizedNode<?, ?> data) {
33             return testValue(data instanceof LeafNode ? ((LeafNode<?>) data).getValue() : null);
34         }
35
36         abstract boolean testValue(Object data);
37     }
38
39     abstract static class AbstractValueDOMQueryPredicate<T> extends AbstractLeafDOMQueryPredicate {
40         private final @NonNull T value;
41
42         AbstractValueDOMQueryPredicate(final YangInstanceIdentifier relativePath, final T value) {
43             super(relativePath);
44             this.value = requireNonNull(value);
45         }
46
47         final @NonNull T value() {
48             return value;
49         }
50
51         @Override
52         ToStringHelper addToStringAttributes(final ToStringHelper helper) {
53             return helper.add("value", value);
54         }
55     }
56
57     abstract static class AbstractComparableDOMQueryPredicate<T extends Comparable<T>>
58             extends AbstractValueDOMQueryPredicate<T> {
59         AbstractComparableDOMQueryPredicate(final YangInstanceIdentifier relativePath, final T value) {
60             super(relativePath, value);
61         }
62
63         @Override
64         @SuppressWarnings("unchecked")
65         public final boolean testValue(final Object data) {
66             return data != null && test(value().compareTo((T) data));
67         }
68
69         abstract boolean test(int valueToData);
70     }
71
72     abstract static class AbstractStringDOMQueryPredicate extends AbstractValueDOMQueryPredicate<String> {
73         AbstractStringDOMQueryPredicate(final YangInstanceIdentifier relativePath, final String value) {
74             super(relativePath, value);
75         }
76
77         @Override
78         public final boolean testValue(final Object data) {
79             return data instanceof String && test((String) data);
80         }
81
82         abstract boolean test(@NonNull String str);
83     }
84
85     public static final class Exists extends DOMQueryPredicate {
86         public Exists(final YangInstanceIdentifier relativePath) {
87             super(relativePath);
88         }
89
90         @Override
91         public boolean test(final NormalizedNode<?, ?> data) {
92             return data != null;
93         }
94     }
95
96     public static final class Not extends DOMQueryPredicate {
97         private final DOMQueryPredicate predicate;
98
99         Not(final DOMQueryPredicate predicate) {
100             super(predicate.relativePath);
101             this.predicate = predicate;
102         }
103
104         public @NonNull DOMQueryPredicate predicate() {
105             return predicate;
106         }
107
108         @Override
109         public DOMQueryPredicate negate() {
110             return predicate;
111         }
112
113         @Override
114         public boolean test(final NormalizedNode<?, ?> data) {
115             return !predicate.test(data);
116         }
117     }
118
119     public static final class ValueEquals<T> extends AbstractValueDOMQueryPredicate<T> {
120         public ValueEquals(final YangInstanceIdentifier relativePath, final T value) {
121             super(relativePath, value);
122         }
123
124         @Override
125         public boolean testValue(final Object data) {
126             return value().equals(data);
127         }
128     }
129
130     public static final class GreaterThan<T extends Comparable<T>> extends AbstractComparableDOMQueryPredicate<T> {
131         public GreaterThan(final YangInstanceIdentifier relativePath, final T value) {
132             super(relativePath, value);
133         }
134
135         @Override
136         boolean test(final int valueToData) {
137             return valueToData <= 0;
138         }
139     }
140
141     public static final class GreaterThanOrEqual<T extends Comparable<T>>
142             extends AbstractComparableDOMQueryPredicate<T> {
143         public GreaterThanOrEqual(final YangInstanceIdentifier relativePath, final T value) {
144             super(relativePath, value);
145         }
146
147         @Override
148         boolean test(final int valueToData) {
149             return valueToData < 0;
150         }
151     }
152
153     public static final class LessThan<T extends Comparable<T>> extends AbstractComparableDOMQueryPredicate<T> {
154         public LessThan(final YangInstanceIdentifier relativePath, final T value) {
155             super(relativePath, value);
156         }
157
158         @Override
159         boolean test(final int valueToData) {
160             return valueToData >= 0;
161         }
162     }
163
164     public static final class LessThanOrEqual<T extends Comparable<T>> extends AbstractComparableDOMQueryPredicate<T> {
165         public LessThanOrEqual(final YangInstanceIdentifier relativePath, final T value) {
166             super(relativePath, value);
167         }
168
169         @Override
170         boolean test(final int valueToData) {
171             return valueToData > 0;
172         }
173     }
174
175     public static final class StartsWith extends AbstractStringDOMQueryPredicate {
176         public StartsWith(final YangInstanceIdentifier relativePath, final String str) {
177             super(relativePath, str);
178         }
179
180         @Override
181         boolean test(final String str) {
182             return str.startsWith(value());
183         }
184     }
185
186     public static final class EndsWith extends AbstractStringDOMQueryPredicate {
187         public EndsWith(final YangInstanceIdentifier relativePath, final String str) {
188             super(relativePath, str);
189         }
190
191         @Override
192         boolean test(final String str) {
193             return str.endsWith(value());
194         }
195     }
196
197     public static final class Contains extends AbstractStringDOMQueryPredicate {
198         public Contains(final YangInstanceIdentifier relativePath, final String str) {
199             super(relativePath, str);
200         }
201
202         @Override
203         boolean test(final String str) {
204             return str.contains(value());
205         }
206     }
207
208     public static final class MatchesPattern extends AbstractLeafDOMQueryPredicate {
209         private final Pattern pattern;
210
211         public MatchesPattern(final YangInstanceIdentifier relativePath, final Pattern pattern) {
212             super(relativePath);
213             this.pattern = requireNonNull(pattern);
214         }
215
216         @Override
217         public boolean testValue(final Object data) {
218             return data instanceof CharSequence && pattern.matcher((CharSequence) data).matches();
219         }
220
221         @Override
222         ToStringHelper addToStringAttributes(final ToStringHelper helper) {
223             return helper.add("pattern", pattern);
224         }
225     }
226
227     private final @NonNull YangInstanceIdentifier relativePath;
228
229     DOMQueryPredicate(final YangInstanceIdentifier relativePath) {
230         this.relativePath = requireNonNull(relativePath);
231     }
232
233     public final @NonNull YangInstanceIdentifier getPath() {
234         return relativePath;
235     }
236
237     @Override
238     public @NonNull DOMQueryPredicate negate() {
239         return new Not(this);
240     }
241
242     @Override
243     public abstract boolean test(@Nullable NormalizedNode<?, ?> data);
244
245     @Override
246     public String toString() {
247         return addToStringAttributes(MoreObjects.toStringHelper(this).add("path", relativePath)).toString();
248     }
249
250     ToStringHelper addToStringAttributes(final ToStringHelper helper) {
251         return helper;
252     }
253 }