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    package org.crsh.lang.java;
020    
021    import org.crsh.cli.impl.invocation.CommandInvoker;
022    import org.crsh.cli.impl.invocation.InvocationException;
023    import org.crsh.cli.impl.invocation.InvocationMatch;
024    import org.crsh.cli.impl.lang.Instance;
025    import org.crsh.command.BaseCommand;
026    import org.crsh.command.CommandContext;
027    import org.crsh.command.InvocationContext;
028    import org.crsh.command.SyntaxException;
029    import org.crsh.console.KeyHandler;
030    import org.crsh.shell.impl.command.InvocationContextImpl;
031    import org.crsh.shell.impl.command.spi.CommandCreationException;
032    
033    import java.io.IOException;
034    import java.lang.reflect.UndeclaredThrowableException;
035    
036    /**
037    * @author Julien Viet
038    */
039    class ProducerCommandImpl<T extends BaseCommand, P> extends CommandImpl<T, Void, P> {
040    
041      private final CommandInvoker<Instance<T>, ?> invoker;
042      private final Class<P> producedType;
043    
044      public ProducerCommandImpl(ShellCommandImpl<T> shellCommand, CommandInvoker<Instance<T>, ?> invoker, Class<P> producedType) {
045        super(shellCommand);
046    
047        //
048        this.invoker = invoker;
049        this.producedType = producedType;
050      }
051    
052      @Override
053      public InvocationMatch<?> getMatch() {
054        return invoker.getMatch();
055      }
056    
057      @Override
058      public Class<P> getProducedType() {
059        return producedType;
060      }
061    
062      @Override
063      public Class<Void> getConsumedType() {
064        return Void.class;
065      }
066    
067      @Override
068      BaseInvoker getInvoker(T command) throws CommandCreationException {
069    
070        //
071        return new BaseInvoker(command) {
072    
073          /** . */
074          private InvocationContext<P> invocationContext;
075    
076          public Class<P> getProducedType() {
077            return producedType;
078          }
079    
080          public Class<Void> getConsumedType() {
081            return Void.class;
082          }
083    
084          public void open(CommandContext<? super P> consumer) {
085            // Java is fine with that but not intellij....
086            CommandContext<P> consumer2 = (CommandContext<P>)consumer;
087            open2(consumer2);
088          }
089    
090          public void open2(final CommandContext<P> consumer) {
091            invocationContext = new InvocationContextImpl<P>(consumer);
092            command.pushContext(invocationContext);
093            command.unmatched = invoker.getMatch().getRest();
094          }
095    
096    
097          @Override
098          public KeyHandler getKeyHandler() {
099            if (command instanceof KeyHandler) {
100              return (KeyHandler)command;
101            } else {
102              return null;
103            }
104          }
105    
106          public void provide(Void element) throws IOException {
107            // Drop everything
108          }
109    
110          public void flush() throws IOException {
111          }
112    
113          public void close() throws IOException, UndeclaredThrowableException {
114    
115            //
116            Object ret;
117            try {
118              ret = invoker.invoke(this);
119            }
120            catch (org.crsh.cli.SyntaxException e) {
121              throw new SyntaxException(e.getMessage());
122            } catch (InvocationException e) {
123              throw command.toScript(e.getCause());
124            }
125    
126            //
127            if (ret != null && producedType.isInstance(ret)) {
128              P produced = producedType.cast(ret);
129              invocationContext.provide(produced);
130            }
131    
132            //
133            invocationContext.flush();
134            invocationContext.close();
135            command.unmatched = null;
136            invocationContext = null;
137          }
138        };
139      }
140    }