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.tokenizer.Tokenizer;
024    
025    import java.util.Iterator;
026    import java.util.LinkedList;
027    import java.util.NoSuchElementException;
028    
029    public final class Parser<T> implements Iterator<Event> {
030    
031      /** . */
032      private final Tokenizer tokenizer;
033    
034      /** . */
035      private final Mode mode;
036    
037      /** . */
038      private CommandDescriptor<T> command;
039    
040      /** . */
041      private Status status;
042    
043      /** . */
044      private final LinkedList<Event> next;
045    
046      public Parser(Tokenizer tokenizer, CommandDescriptor<T> command, Mode mode) {
047        this.tokenizer = tokenizer;
048        this.command = command;
049        this.status = new Status.ReadingOption();
050        this.mode = mode;
051        this.next = new LinkedList<Event>();
052      }
053    
054      Status getStatus() {
055        return status;
056      }
057    
058      public boolean hasNext() {
059        if (next.isEmpty()) {
060          determine();
061        }
062        return next.size() > 0;
063      }
064    
065      public Event next() {
066        if (!hasNext()) {
067          throw new NoSuchElementException();
068        }
069        return next.removeFirst();
070      }
071    
072      public void remove() {
073        throw new UnsupportedOperationException();
074      }
075    
076      private void determine() {
077        while (next.isEmpty()) {
078          Status.Response<T> nextStatus = status.process(new Status.Request<T>(mode, tokenizer, command));
079          if (nextStatus.status != null) {
080            this.status = nextStatus.status;
081          }
082          if (nextStatus.events != null) {
083            next.addAll(nextStatus.events);
084          }
085          if (nextStatus.command != null) {
086            command = (CommandDescriptor<T>)nextStatus.command;
087          }
088        }
089      }
090    }