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