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.shell.impl.command.pipeline;
020    
021    import org.crsh.command.CommandContext;
022    import org.crsh.shell.impl.command.spi.CommandException;
023    import org.crsh.stream.Consumer;
024    import org.crsh.stream.Producer;
025    import org.crsh.text.Screenable;
026    import org.crsh.text.ScreenContext;
027    import org.crsh.shell.impl.command.spi.CommandInvoker;
028    import org.crsh.text.CLS;
029    import org.crsh.text.ScreenContextConsumer;
030    import org.crsh.text.Style;
031    
032    import java.io.IOException;
033    import java.lang.reflect.UndeclaredThrowableException;
034    import java.util.Map;
035    
036    /** @author Julien Viet */
037    class CommandInvokerAdapter<C, P, CONSUMER extends CommandContext<? super P>>
038        implements Consumer<Object>, Producer<P, CONSUMER>, CommandContext<Object> {
039    
040      /** . */
041      final CommandInvoker<C, P> command;
042    
043      /** . */
044      protected CONSUMER consumer;
045    
046      /** . */
047      private final Class<C> consumedType;
048    
049      /** . */
050      private final Class<P> producedType;
051    
052      /** . */
053      private ScreenContextConsumer adapter;
054    
055      /** . */
056      private ScreenContext screenContext;
057    
058      /** . */
059      private final boolean charSequenceConsumer;
060    
061      /** . */
062      private final boolean styleConsumer;
063    
064      /** . */
065      private final boolean clsConsumer;
066    
067      CommandInvokerAdapter(CommandInvoker<C, P> command, Class<C> consumedType, Class<P> producedType) {
068        this.consumedType = consumedType;
069        this.producedType = producedType;
070        this.consumer = null;
071        this.command = command;
072        this.screenContext = null;
073        this.charSequenceConsumer = consumedType.isAssignableFrom(CharSequence.class);
074        this.styleConsumer = consumedType.isAssignableFrom(Style.class);
075        this.clsConsumer = consumedType.isAssignableFrom(CLS.class);
076      }
077    
078      public boolean takeAlternateBuffer() throws IOException {
079        return consumer.takeAlternateBuffer();
080      }
081    
082      public boolean releaseAlternateBuffer() throws IOException {
083        return consumer.releaseAlternateBuffer();
084      }
085    
086      public String getProperty(String propertyName) {
087        return consumer.getProperty(propertyName);
088      }
089    
090      public String readLine(String msg, boolean echo) throws IOException, InterruptedException {
091        return consumer.readLine(msg, echo);
092      }
093    
094      public Map<String, Object> getSession() {
095        return consumer.getSession();
096      }
097    
098      public Map<String, Object> getAttributes() {
099        return consumer.getAttributes();
100      }
101    
102      public int getWidth() {
103        return screenContext != null ? screenContext.getWidth() : consumer.getWidth();
104      }
105    
106      public int getHeight() {
107        return screenContext != null ? screenContext.getHeight() : consumer.getHeight();
108      }
109    
110      public void open(final CONSUMER consumer) throws Exception {
111    
112        //
113        try {
114          command.open(consumer);
115        }
116        catch (CommandException e) {
117          Throwable cause = e.getCause();
118          if (cause instanceof Exception) {
119            throw (Exception)cause;
120          } else if (cause instanceof Error) {
121            throw (Error)cause;
122          } else {
123            throw new UndeclaredThrowableException(cause);
124          }
125        }
126    
127        //
128        ScreenContext screenContext = command.getScreenContext();
129        ScreenContextConsumer adapter = screenContext != null ? new ScreenContextConsumer(screenContext) : null;
130    
131        //
132        this.screenContext = screenContext;
133        this.adapter = adapter;
134        this.consumer = consumer;
135      }
136    
137      @Override
138      public Class<Object> getConsumedType() {
139        return Object.class;
140      }
141    
142      @Override
143      public Class<P> getProducedType() {
144        return producedType;
145      }
146    
147      @Override
148      public void provide(Object element) throws Exception  {
149        if (adapter != null) {
150          adapter.provide(element);
151        }
152        if (consumedType.isInstance(element)) {
153          try {
154            command.provide(consumedType.cast(element));
155          }
156          catch (CommandException e) {
157            Throwable cause = e.getCause();
158            if (cause instanceof Exception) {
159              throw (Exception)cause;
160            } else if (cause instanceof Error) {
161              throw (Error)cause;
162            } else {
163              throw new UndeclaredThrowableException(cause);
164            }
165          }
166        }
167      }
168    
169      @Override
170      public Appendable append(char c) throws IOException {
171        if (screenContext != null) {
172          screenContext.append(c);
173        }
174        if (charSequenceConsumer) {
175          try {
176            command.provide(consumedType.cast(Character.toString(c)));
177          }
178          catch (CommandException e) {
179            Throwable cause = e.getCause();
180            if (cause instanceof RuntimeException) {
181              throw (RuntimeException)cause;
182            } else if (cause instanceof Error) {
183              throw (Error)cause;
184            } else {
185              throw new UndeclaredThrowableException(cause);
186            }
187          }
188        }
189        return this;
190      }
191    
192      @Override
193      public Appendable append(CharSequence s) throws IOException {
194        if (screenContext != null) {
195          screenContext.append(s);
196        }
197        if (charSequenceConsumer) {
198          try {
199            command.provide(consumedType.cast(s));
200          }
201          catch (CommandException e) {
202            Throwable cause = e.getCause();
203            if (cause instanceof RuntimeException) {
204              throw (RuntimeException)cause;
205            } else if (cause instanceof Error) {
206              throw (Error)cause;
207            } else {
208              throw new UndeclaredThrowableException(cause);
209            }
210          }
211        }
212        return this;
213      }
214    
215      @Override
216      public Appendable append(CharSequence csq, int start, int end) throws IOException {
217        if (screenContext != null) {
218          screenContext.append(csq, start, end);
219        }
220        if (charSequenceConsumer) {
221          try {
222            command.provide(consumedType.cast(csq.subSequence(start, end)));
223          }
224          catch (CommandException e) {
225            Throwable cause = e.getCause();
226            if (cause instanceof RuntimeException) {
227              throw (RuntimeException)cause;
228            } else if (cause instanceof Error) {
229              throw (Error)cause;
230            } else {
231              throw new UndeclaredThrowableException(cause);
232            }
233          }
234        }
235        return this;
236      }
237    
238      @Override
239      public Screenable append(Style style) throws IOException {
240        if (screenContext != null) {
241          screenContext.append(style);
242        }
243        if (styleConsumer) {
244          try {
245            command.provide(consumedType.cast(style));
246          }
247          catch (CommandException e) {
248            Throwable cause = e.getCause();
249            if (cause instanceof RuntimeException) {
250              throw (RuntimeException)cause;
251            } else if (cause instanceof Error) {
252              throw (Error)cause;
253            } else {
254              throw new UndeclaredThrowableException(cause);
255            }
256          }
257        }
258        return this;
259      }
260    
261      @Override
262      public Screenable cls() throws IOException {
263        if (screenContext != null) {
264          screenContext.cls();
265        }
266        if (clsConsumer) {
267          try {
268            command.provide(consumedType.cast(CLS.INSTANCE));
269          }
270          catch (CommandException e) {
271            Throwable cause = e.getCause();
272            if (cause instanceof RuntimeException) {
273              throw (RuntimeException)cause;
274            } else if (cause instanceof Error) {
275              throw (Error)cause;
276            } else {
277              throw new UndeclaredThrowableException(cause);
278            }
279          }
280        }
281        return this;
282      }
283    
284      public void flush() throws IOException {
285        if (adapter != null) {
286          adapter.flush();
287        }
288        command.flush();
289      }
290    
291      public void close() throws Exception {
292        if (adapter != null) {
293          adapter.flush();
294        }
295        try {
296          command.close();
297        }
298        catch (CommandException e) {
299          Throwable cause = e.getCause();
300          if (cause instanceof Exception) {
301            throw (Exception)cause;
302          } else if (cause instanceof Error) {
303            throw (Error)cause;
304          } else {
305            throw new UndeclaredThrowableException(cause);
306          }
307        }
308      }
309    }