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

Last change on this file since 6935 was 6935, checked in by Oliver Schonefeld, 8 years ago
  • update/add copyright
  • fix typo in class name
  • minor changes
  • Property svn:eol-style set to native
File size: 6.9 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    protected final QueryNodeType nodeType;
29    protected final List<QueryNode> children;
30    protected QueryNode parent;
31
32
33    /**
34     * Constructor.
35     *
36     * @param nodeType
37     *            the type of the node
38     * @param children
39     *            the children of this node or <code>null</code> if none
40     */
41    protected QueryNode(QueryNodeType nodeType, List<QueryNode> children) {
42        this.nodeType = nodeType;
43        if ((children != null) && !children.isEmpty()) {
44            for (QueryNode child : children) {
45                child.setParent(this);
46            }
47            this.children = Collections.unmodifiableList(children);
48        } else {
49            this.children = Collections.emptyList();
50        }
51    }
52
53
54    /**
55     * Constructor.
56     *
57     * @param nodeType
58     *            the type of the node
59     * @param child
60     *            the child of this node or <code>null</code> if none
61     */
62    protected QueryNode(QueryNodeType nodeType, QueryNode child) {
63        this.nodeType = nodeType;
64        if (child != null) {
65            child.setParent(this);
66            this.children = Collections.singletonList(child);
67        } else {
68            this.children = Collections.emptyList();
69        }
70    }
71
72
73    /**
74     * Constructor.
75     *
76     * @param nodeType
77     *            the type of the node
78     */
79    protected QueryNode(QueryNodeType nodeType) {
80        this.nodeType = nodeType;
81        this.children = Collections.emptyList();
82    }
83
84
85    /**
86     * Get the node type of this node.
87     *
88     * @return the node type
89     */
90    public QueryNodeType getNodeType() {
91        return nodeType;
92    }
93
94
95    /**
96     * Get the parent node of this node.
97     *
98     * @return the parent node or <code>null</code> if this is the root node
99     */
100    public QueryNode getParent() {
101        return parent;
102    }
103
104
105    /**
106     * The children of this node.
107     *
108     * @return the list of children of this node
109     */
110    public List<QueryNode> getChildren() {
111        return children;
112    }
113
114
115    /**
116     * Get the number of children of this node.
117     *
118     * @return the number of children of this node
119     */
120    public int getChildCount() {
121        final List<QueryNode> children = getChildren();
122        return (children != null) ? children.size() : 0;
123    }
124
125
126    /**
127     * Get a child node by index.
128     *
129     * @param idx
130     *            the index of the child node
131     * @return the child node of this node or <code>null</code> if index is out
132     *         of bounds
133     */
134    public QueryNode getChild(int idx) {
135        final List<QueryNode> children = getChildren();
136        if ((children != null) && !children.isEmpty()) {
137            if ((idx >= 0) && (idx < children.size())) {
138                return children.get(idx);
139            }
140        }
141        return null;
142    }
143
144
145    /**
146     * Get this first child node.
147     *
148     * @return the first child node of this node or <code>null</code> if none
149     */
150    public QueryNode getFirstChild() {
151        return getChild(0);
152    }
153
154
155    /**
156     * Get this last child node.
157     *
158     * @return the last child node of this node or <code>null</code> if none
159     */
160    public QueryNode getLastChild() {
161        return getChild(getChildCount() - 1);
162    }
163
164
165    /**
166     * Get a child node of specified type by index. Only child nodes of the
167     * requested type are counted.
168     *
169     * @param clazz
170     *            the type to nodes to be considered
171     * @param idx
172     *            the index of the child node
173     * @return the child node of this node or <code>null</code> if no child was
174     *         found
175     */
176    public <T extends QueryNode> T getChild(Class<T> clazz, int idx) {
177        final List<QueryNode> children = getChildren();
178        if (!children.isEmpty()) {
179            int pos = 0;
180            for (QueryNode child : children) {
181                if (clazz.isInstance(child)) {
182                    if (pos == idx) {
183                        return clazz.cast(child);
184                    }
185                    pos++;
186                }
187            }
188        }
189        return null;
190    }
191
192
193    /**
194     * Get a first child node of specified type.
195     *
196     * @return the child node of this node or <code>null</code> if no child was
197     *         found
198     */
199    public <T extends QueryNode> T getFirstChild(Class<T> clazz) {
200            return getChild(clazz, 0);
201    }
202
203
204    @Override
205    public String toString() {
206        StringBuilder sb = new StringBuilder();
207        sb.append("(").append(nodeType.toDisplayString());
208        if (!children.isEmpty()) {
209            for (QueryNode child : children) {
210                sb.append(" ").append(child);
211            }
212        }
213        sb.append(")");
214        return sb.toString();
215    }
216
217
218    public abstract void accept(QueryVisitor visitor);
219
220
221    protected final void setParent(QueryNode parent) {
222        this.parent = parent;
223    }
224
225
226    protected final void visitAnyNode(QueryVisitor vistor, QueryNode node) {
227        if (node instanceof QueryDisjunction) {
228            vistor.visit((QueryDisjunction) node);
229        } else if (node instanceof QueryGroup) {
230            vistor.visit((QueryGroup) node);
231        } else if (node instanceof QuerySegment) {
232            vistor.visit((QuerySegment) node);
233        } else if (node instanceof QuerySequence) {
234            vistor.visit((QuerySequence) node);
235        } else if (node instanceof ExpressionAnd) {
236            vistor.visit((ExpressionAnd) node);
237        } else if (node instanceof Expression) {
238            vistor.visit((Expression) node);
239        } else if (node instanceof ExpressionGroup) {
240            vistor.visit((ExpressionGroup) node);
241        } else if (node instanceof ExpressionNot) {
242            vistor.visit((ExpressionNot) node);
243        } else if (node instanceof ExpressionOr) {
244            vistor.visit((ExpressionOr) node);
245        } else if (node instanceof ExpressionWildcard) {
246            vistor.visit((ExpressionWildcard) node);
247        } else if (node instanceof SimpleWithin) {
248            vistor.visit((SimpleWithin) node);
249        } else {
250            throw new RuntimeException("unexpected node type: "  +
251                    node.getNodeType());
252        }
253    }
254
255} // abstract class QueryNode
Note: See TracBrowser for help on using the repository browser.