source: FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/parser/QueryNode.java @ 7163

Last change on this file since 7163 was 7163, checked in by Oliver Schonefeld, 6 years ago
  • get rid of Contants class and move constant to QueryNode?
  • Property svn:eol-style set to native
File size: 6.4 KB
Line 
1/**
2 * This software is copyright (c) 2013-2016 by
3 *  - Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
4 * This is free software. You can redistribute it
5 * and/or modify it under the terms described in
6 * the GNU General Public License v3 of which you
7 * should have received a copy. Otherwise you can download
8 * it from
9 *
10 *   http://www.gnu.org/licenses/gpl-3.0.txt
11 *
12 * @copyright Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
13 *
14 * @license http://www.gnu.org/licenses/gpl-3.0.txt
15 *  GNU General Public License v3
16 */
17package eu.clarin.sru.server.fcs.parser;
18
19import java.util.Collections;
20import java.util.List;
21
22
23/**
24 * base class for FCS-QL expression tree nodes.
25 *
26 */
27public abstract class QueryNode {
28    /**
29     * Atom occurrence it not bound.
30     */
31    public static final int OCCURS_UNBOUNDED = -1;
32    protected final QueryNodeType nodeType;
33    protected final List<QueryNode> children;
34    protected QueryNode parent;
35
36
37    /**
38     * Constructor.
39     *
40     * @param nodeType
41     *            the type of the node
42     * @param children
43     *            the children of this node or <code>null</code> if none
44     */
45    protected QueryNode(QueryNodeType nodeType, List<QueryNode> children) {
46        this.nodeType = nodeType;
47        if ((children != null) && !children.isEmpty()) {
48            for (QueryNode child : children) {
49                child.setParent(this);
50            }
51            this.children = Collections.unmodifiableList(children);
52        } else {
53            this.children = Collections.emptyList();
54        }
55    }
56
57
58    /**
59     * Constructor.
60     *
61     * @param nodeType
62     *            the type of the node
63     * @param child
64     *            the child of this node or <code>null</code> if none
65     */
66    protected QueryNode(QueryNodeType nodeType, QueryNode child) {
67        this.nodeType = nodeType;
68        if (child != null) {
69            child.setParent(this);
70            this.children = Collections.singletonList(child);
71        } else {
72            this.children = Collections.emptyList();
73        }
74    }
75
76
77    /**
78     * Constructor.
79     *
80     * @param nodeType
81     *            the type of the node
82     */
83    protected QueryNode(QueryNodeType nodeType) {
84        this.nodeType = nodeType;
85        this.children = Collections.emptyList();
86    }
87
88
89    /**
90     * Get the node type of this node.
91     *
92     * @return the node type
93     */
94    public QueryNodeType getNodeType() {
95        return nodeType;
96    }
97
98
99    /**
100     * Check, if node if of given type.
101     *
102     * @param nodeType
103     *            type to check against
104     * @return <code>true</code> if node is of given type, <code>false</code>
105     *         otherwise
106     */
107    public boolean hasNodeType(QueryNodeType nodeType) {
108        if (nodeType == null) {
109            throw new NullPointerException("nodeType == null");
110        }
111        return this.nodeType == nodeType;
112    }
113
114
115    /**
116     * Get the parent node of this node.
117     *
118     * @return the parent node or <code>null</code> if this is the root node
119     */
120    public QueryNode getParent() {
121        return parent;
122    }
123
124
125    /**
126     * The children of this node.
127     *
128     * @return the list of children of this node
129     */
130    public List<QueryNode> getChildren() {
131        return children;
132    }
133
134
135    /**
136     * Get the number of children of this node.
137     *
138     * @return the number of children of this node
139     */
140    public int getChildCount() {
141        final List<QueryNode> children = getChildren();
142        return (children != null) ? children.size() : 0;
143    }
144
145
146    /**
147     * Get a child node by index.
148     *
149     * @param idx
150     *            the index of the child node
151     * @return the child node of this node or <code>null</code> if index is out
152     *         of bounds
153     */
154    public QueryNode getChild(int idx) {
155        final List<QueryNode> children = getChildren();
156        if ((children != null) && !children.isEmpty()) {
157            if ((idx >= 0) && (idx < children.size())) {
158                return children.get(idx);
159            }
160        }
161        return null;
162    }
163
164
165    /**
166     * Get this first child node.
167     *
168     * @return the first child node of this node or <code>null</code> if none
169     */
170    public QueryNode getFirstChild() {
171        return getChild(0);
172    }
173
174
175    /**
176     * Get this last child node.
177     *
178     * @return the last child node of this node or <code>null</code> if none
179     */
180    public QueryNode getLastChild() {
181        return getChild(getChildCount() - 1);
182    }
183
184
185    /**
186     * Get a child node of specified type by index. Only child nodes of the
187     * requested type are counted.
188     *
189     * @param <T>
190     *            the class of the nodes to be considered
191     * @param clazz
192     *            the type to nodes to be considered
193     * @param idx
194     *            the index of the child node
195     * @return the child node of this node or <code>null</code> if no child was
196     *         found
197     */
198    public <T extends QueryNode> T getChild(Class<T> clazz, int idx) {
199        final List<QueryNode> children = getChildren();
200        if (!children.isEmpty()) {
201            int pos = 0;
202            for (QueryNode child : children) {
203                if (clazz.isInstance(child)) {
204                    if (pos == idx) {
205                        return clazz.cast(child);
206                    }
207                    pos++;
208                }
209            }
210        }
211        return null;
212    }
213
214
215    /**
216     * Get a first child node of specified type.
217     *
218     * @param <T>
219     *            the class of the nodes to be considered
220     * @param clazz
221     *            the type to nodes to be considered
222     * @return the child node of this node or <code>null</code> if no child was
223     *         found
224     */
225    public <T extends QueryNode> T getFirstChild(Class<T> clazz) {
226            return getChild(clazz, 0);
227    }
228
229
230    @Override
231    public String toString() {
232        StringBuilder sb = new StringBuilder();
233        sb.append("(").append(nodeType.toDisplayString());
234        if (!children.isEmpty()) {
235            for (QueryNode child : children) {
236                sb.append(" ").append(child);
237            }
238        }
239        sb.append(")");
240        return sb.toString();
241    }
242
243
244    public abstract void accept(QueryVisitor visitor);
245
246
247    protected final void setParent(QueryNode parent) {
248        this.parent = parent;
249    }
250
251} // abstract class QueryNode
Note: See TracBrowser for help on using the repository browser.