001    /*
002     * Copyright (C) 2012 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    
020    package org.crsh.cli.impl.parser;
021    
022    import org.crsh.cli.descriptor.CommandDescriptor;
023    import org.crsh.cli.impl.Delimiter;
024    import org.crsh.cli.impl.tokenizer.Tokenizer;
025    
026    import java.util.Iterator;
027    import java.util.LinkedList;
028    import java.util.NoSuchElementException;
029    
030    public final class Parser<T> implements Iterator<Event> {
031    
032      /** . */
033      private final Tokenizer tokenizer;
034    
035      /** . */
036      private final String mainName;
037    
038      /** . */
039      private final Mode mode;
040    
041      /** . */
042      private CommandDescriptor<T> command;
043    
044      /** . */
045      private Status status;
046    
047      /** . */
048      private final LinkedList<Event> next;
049    
050      public Parser(Tokenizer tokenizer, CommandDescriptor<T> command, String mainName, Mode mode) {
051        this.tokenizer = tokenizer;
052        this.command = command;
053        this.mainName = mainName;
054        this.status = new Status.ReadingOption();
055        this.mode = mode;
056        this.next = new LinkedList<Event>();
057      }
058    
059      Status getStatus() {
060        return status;
061      }
062    
063      public Delimiter getDelimiter() {
064        return tokenizer.getDelimiter();
065      }
066    
067      public boolean hasNext() {
068        if (next.isEmpty()) {
069          determine();
070        }
071        return next.size() > 0;
072      }
073    
074      public Event next() {
075        if (!hasNext()) {
076          throw new NoSuchElementException();
077        }
078        return next.removeFirst();
079      }
080    
081      public void remove() {
082        throw new UnsupportedOperationException();
083      }
084    
085      private void determine() {
086        while (next.isEmpty()) {
087          Status.Response<T> nextStatus = status.process(new Status.Request<T>(mode, mainName, tokenizer, command));
088          if (nextStatus.status != null) {
089            this.status = nextStatus.status;
090          }
091          if (nextStatus.events != null) {
092            next.addAll(nextStatus.events);
093          }
094          if (nextStatus.command != null) {
095            command = (CommandDescriptor<T>)nextStatus.command;
096          }
097        }
098      }
099    }