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.shell.impl.command;
021    
022    import org.crsh.command.CommandContext;
023    import org.crsh.command.ScriptException;
024    import org.crsh.shell.InteractionContext;
025    import org.crsh.io.Filter;
026    import org.crsh.shell.ScreenContext;
027    import org.crsh.text.Chunk;
028    import org.crsh.text.ChunkAdapter;
029    
030    import java.io.IOException;
031    import java.util.Map;
032    
033    /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
034    abstract class Pipe<C, P> implements Filter<C, P, CommandContext<P>>, CommandContext<C> {
035    
036      /** . */
037      protected CommandContext<P> context;
038    
039      public final boolean takeAlternateBuffer() throws IOException {
040        return context.takeAlternateBuffer();
041      }
042    
043      public final boolean releaseAlternateBuffer() throws IOException {
044        return context.releaseAlternateBuffer();
045      }
046    
047      public final String getProperty(String propertyName) {
048        return context.getProperty(propertyName);
049      }
050    
051      public final String readLine(String msg, boolean echo) {
052        return context.readLine(msg, echo);
053      }
054    
055      public final int getWidth() {
056        return context.getWidth();
057      }
058    
059      public final int getHeight() {
060        return context.getHeight();
061      }
062    
063      public Map<String, Object> getSession() {
064        return context.getSession();
065      }
066    
067      public Map<String, Object> getAttributes() {
068        return context.getAttributes();
069      }
070    
071      /**
072       * A pipe filter that invokes a command through a {@link org.crsh.command.CommandInvoker}.
073       */
074      static class Invoker<C, P> extends Pipe<C, P> {
075    
076        /** . */
077        final Filter<C, P, InteractionContext<P>> command;
078    
079        Invoker(Filter<C, P, InteractionContext<P>> command) {
080          this.command = command;
081        }
082    
083        public void setPiped(boolean piped) {
084          command.setPiped(piped);
085        }
086    
087        public Class<P> getProducedType() {
088          return command.getProducedType();
089        }
090    
091        public Class<C> getConsumedType() {
092          return command.getConsumedType();
093        }
094    
095        public void open(CommandContext<P> consumer) {
096          this.context = consumer;
097          this.command.open(consumer);
098        }
099    
100        public void provide(C element) throws IOException {
101          if (command.getConsumedType().isInstance(element)) {
102            command.provide(element);
103          }
104        }
105    
106        public void flush() throws IOException {
107          command.flush();
108        }
109    
110        public void close() throws ScriptException {
111          command.close();
112        }
113      }
114    
115      static class Chunkizer extends Pipe<Object, Chunk> {
116    
117        /** . */
118        private ChunkAdapter ca;
119    
120        public Class<Chunk> getProducedType() {
121          return Chunk.class;
122        }
123    
124        public Class<Object> getConsumedType() {
125          return Object.class;
126        }
127    
128        public void setPiped(boolean piped) {
129          ((Pipe<Chunk, ?>)context).setPiped(piped);
130        }
131    
132        public void open(final CommandContext<Chunk> consumer) {
133          ca = new ChunkAdapter(new ScreenContext<Chunk>() {
134            public int getWidth() {
135              return consumer.getWidth();
136            }
137            public int getHeight() {
138              return consumer.getHeight();
139            }
140            public Class<Chunk> getConsumedType() {
141              return Chunk.class;
142            }
143            public void provide(Chunk element) throws IOException {
144              Chunkizer.this.context.provide(element);
145            }
146            public void flush() throws IOException {
147              Chunkizer.this.context.flush();
148            }
149          });
150    
151          this.context = consumer;
152        }
153    
154        public void provide(Object element) throws ScriptException, IOException {
155          ca.provide(element);
156        }
157    
158        public void flush() throws ScriptException, IOException {
159          ca.flush();
160        }
161    
162        public void close() throws ScriptException {
163          ((Pipe<Chunk, ?>)context).close();
164        }
165      }
166    
167      static class Sink<P> extends Pipe<Object, P> {
168    
169        /** . */
170        private final Class<P> producedType;
171    
172        Sink(Class<P> producedType) {
173          this.producedType = producedType;
174        }
175    
176        public Class<P> getProducedType() {
177          return producedType;
178        }
179    
180        public void setPiped(boolean piped) {
181        }
182    
183        public void open(CommandContext<P> consumer) {
184          this.context = consumer;
185        }
186    
187        public void provide(Object element) throws IOException {
188        }
189    
190        public Class<Object> getConsumedType() {
191          return Object.class;
192        }
193    
194        public void flush() throws IOException {
195          context.flush();
196        }
197    
198        public void close() {
199          ((Pipe<P, ?>)context).close();
200        }
201      }
202    }