001package gudusoft.gsqlparser.nodes;
002
003
004import gudusoft.gsqlparser.ESqlClause;
005import gudusoft.gsqlparser.TCustomSqlStatement;
006import gudusoft.gsqlparser.TSourceToken;
007
008import java.util.ArrayList;
009import java.util.Iterator;
010import java.util.Vector;
011
012/**
013 * List of parse tree node.
014 */
015public class TParseTreeNodeList<T extends TParseTreeNode> extends TParseTreeNode implements Iterable<T> {
016
017    public void addAll(TParseTreeNodeList sourceList){
018        v.addAll(sourceList.v);
019    }
020    public void clear(){
021        v.clear();
022    }
023    public void setListSeparatedByComma(boolean listSeparatedByComma) {
024        this.listSeparatedByComma = listSeparatedByComma;
025    }
026
027    public boolean isListSeparatedByComma() {
028        return listSeparatedByComma;
029    }
030
031    private boolean listSeparatedByComma = true;
032
033    @Override
034    public Iterator<T> iterator() {
035        return new TParseTreeNodeList.NodeSetIterator();
036    }
037
038    private class NodeSetIterator implements Iterator {
039        private int currentIndex = 0;
040
041        @Override
042        public boolean hasNext() {
043           return (currentIndex < size())&&(size()>0);
044        }
045
046        @Override
047        public T next() {
048            return elementAt(currentIndex++);
049        }
050
051        @Override
052        public void remove() {
053            throw new UnsupportedOperationException();
054        }
055    }
056
057
058    public void TParseTreeNodeList(){
059    }
060
061
062    private ArrayList<T> v = new ArrayList();
063
064    public final int size()
065    {
066        return v.size();
067    }
068
069    public T elementAt(int index)
070    {
071        return  v.get(index);
072    }
073
074    public final void addElement(T ptn)
075    {
076
077        TParseTreeNode node = (TParseTreeNode)ptn;
078        if ((node!=null)&&(!node.isTokensInChain())){
079            if (this.size()>0){
080                getElement(this.size()-1).appendNewNode(node,true);
081            }else{
082
083            }
084        }
085
086        v.add(ptn);
087    }
088
089    public final void removeElementWithoutSyncTokens(int index)
090    {
091         v.remove(index);
092    }
093
094    public final void removeElementAt(int index)
095    {
096       this.removeItem(index);
097    }
098
099    public final boolean removeElement(TParseTreeNode ptn)
100    {
101        return v.remove(ptn);
102    }
103
104    final TParseTreeNode removeAndSyncTokens(int index)
105    {
106        if(TParseTreeNode.doubleLinkedTokenListToString){
107            TParseTreeNode node = (TParseTreeNode) getElement(index);
108            if (node.getNodeStatus() != ENodeStatus.nsRemoved){
109                node.removeTokens();
110            }
111            v.remove(index);
112            // remove unnecessary comma if any
113            if (this.size() != 0){
114                TSourceToken lcPrevToken = null;
115                if (this.getStartToken()!=null){
116                    lcPrevToken = this.getStartToken().getPrevTokenInChain();
117                }
118                while (lcPrevToken != null){
119                    if (lcPrevToken.tokencode == ','){
120                        lcPrevToken.removeFromChain();
121                        break;
122                    }
123                    if (lcPrevToken.issolidtoken()){
124                        break;
125                    }
126                    lcPrevToken = lcPrevToken.getPrevTokenInChain();
127                }
128
129                TSourceToken lcNextToken = null;
130                if (this.getEndToken() != null){
131                    lcNextToken = this.getEndToken().getNextTokenInChain();
132                }
133                while (lcNextToken != null){
134                    if (lcNextToken.tokencode == ','){
135                        lcNextToken.updateNodeEndWithThisToken();
136                        lcNextToken.removeFromChain();
137                        break;
138                    }
139                    if (lcNextToken.issolidtoken()){
140                        break;
141                    }
142                    lcNextToken = lcNextToken.getNextTokenInChain();
143                }
144                lcNextToken = null;
145                if (this.getStartToken() != null){
146                    lcNextToken = this.getStartToken().getNextTokenInChain();
147                }
148                boolean foundComma = false;
149                while (lcNextToken != null){
150                    if (lcNextToken.tokencode == ','){
151                        if (foundComma){
152                            lcNextToken.removeFromChain();
153                            break;
154                        }else{
155                            foundComma = true;
156                        }
157                    }else if (lcNextToken.issolidtoken()){
158                        foundComma = false;
159                    }
160                    lcNextToken = lcNextToken.getNextTokenInChain();
161                    if (lcNextToken == this.getEndToken()) break;
162                }
163
164            }
165
166            return node;
167
168//            if (index == 0){
169//                // first element
170//                if (size() > 1){
171//                    TSourceToken st = node.getEndToken().searchToken(",",1);
172//                    if (st != null){
173//                        st.removeFromChain();
174//                    }
175//                }
176//            }else{
177//                // second or later token
178//                TSourceToken st = node.getStartToken().searchToken(",",-1);
179//                if (st != null){
180//                    st.removeFromChain();
181//                }
182//            }
183        }else {
184            return((TParseTreeNode) (v.remove(index)));
185        }
186
187    }
188
189    public final int indexOf(TParseTreeNode ptn)
190    {
191        return v.indexOf(ptn);
192    }
193
194    final void setElementAt(T ptn, int index)
195    {
196        v.set(index,ptn);
197    }
198
199
200    public final void insertElementAt(T ptn, int index)
201    {
202        TParseTreeNode node = (TParseTreeNode)ptn;
203        if (!node.isTokensInChain()){
204            if ((this.size()>0)&&(index < this.size())){
205                getElement(index).insertNewNodeBeforeMe(node,true);
206            }else{
207
208            }
209        }
210
211        v.add(index,ptn);
212    }
213
214    public void init(Object arg1)
215    {
216        addParseTreeNode(arg1);
217    }
218
219    public void init(Object arg1,Object arg2)
220    {
221        addParseTreeNode(arg1);
222        addParseTreeNode(arg2);
223    }
224
225    public void init(Object arg1,Object arg2,Object arg3)
226    {
227        addParseTreeNode(arg1);
228        addParseTreeNode(arg2);
229        addParseTreeNode(arg3);
230    }
231
232    public void init(Object arg1,Object arg2,Object arg3,Object arg4)
233    {
234        addParseTreeNode(arg1);
235        addParseTreeNode(arg2);
236        addParseTreeNode(arg3);
237        addParseTreeNode(arg4);
238    }
239
240    void addParseTreeNode(Object arg1){
241        addElement((T)arg1);
242    }
243
244    public void addNode(Object arg1){
245      addParseTreeNode((TParseTreeNode)arg1);  
246    }
247
248
249    public  TParseTreeNode getElement(int index){
250        return elementAt(index);
251    }
252    /**
253     * analyze this node
254     */
255    public void doParse(TCustomSqlStatement psql, ESqlClause plocation){
256     for(int i=0; i<size();i++){
257         if (elementAt(i) != null){
258            elementAt(i).doParse(psql,plocation);
259         }
260     }
261    }
262
263
264    public TSourceToken getStartToken() {
265        if (size() == 0){
266            return null;
267        }else{
268            return elementAt(0).getStartToken();
269        }
270    }
271
272    public TSourceToken getEndToken() {
273        if (size() == 0){
274            return null;
275        }else{
276            return elementAt(size()-1).getEndToken();
277        }
278    }
279
280    public void accept(TParseTreeVisitor v){
281        v.preVisit(this);
282        v.postVisit(this);
283    }
284
285    public void acceptChildren(TParseTreeVisitor v){
286        v.preVisit(this);
287        for(int i=0; i<size();i++){
288            if (elementAt(i) != null){
289                elementAt(i).acceptChildren(v);
290            }
291        }
292        v.postVisit(this);
293    }
294
295    public TParseTreeNode removeItem(int index){
296        return removeAndSyncTokens(index);
297    }
298}