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 */
019package org.crsh.lang.impl.groovy.closure;
020
021import groovy.lang.Closure;
022import org.crsh.command.CommandContext;
023import org.crsh.shell.ErrorKind;
024import org.crsh.shell.impl.command.spi.CommandException;
025import org.crsh.shell.impl.command.spi.CommandInvoker;
026
027import java.io.IOException;
028
029/** @author Julien Viet */
030public class ClosureInvoker extends CommandInvoker<Object, Object> {
031
032  /** . */
033  private final Closure closure;
034
035  /** . */
036  private final Class<?> type;
037
038  /** . */
039  private CommandContext<? super Object> consumer;
040
041  public ClosureInvoker(Closure closure) {
042
043    // Resolve the closure consumed type
044    final Class<?> type;
045    Class[] parameterTypes = closure.getParameterTypes();
046    if (parameterTypes != null && parameterTypes.length > 0) {
047      type = parameterTypes[0];
048    } else {
049      type = Object.class;
050    }
051
052    //
053    this.type = type;
054    this.closure = closure;
055  }
056
057  public Class<Object> getProducedType() {
058    return Object.class;
059  }
060
061  public Class<Object> getConsumedType() {
062    return Object.class;
063  }
064
065  public void provide(Object element) throws IOException, CommandException {
066    if (type.isInstance(element)) {
067      Object ret = closure.call(element);
068      if (ret != null) {
069        try {
070          consumer.provide(ret);
071        }
072        catch (Exception e) {
073          throw new CommandException(ErrorKind.EVALUATION, e);
074        }
075      }
076    }
077  }
078
079  public void open(CommandContext<? super Object> consumer) {
080    this.consumer = consumer;
081    ClosureDelegate delegate = new ClosureDelegate(consumer, closure.getOwner());
082    closure.setResolveStrategy(Closure.DELEGATE_FIRST);
083    closure.setDelegate(delegate);
084  }
085
086  public void flush() throws IOException {
087    consumer.flush();
088  }
089
090  public void close() {
091    consumer = null;
092  }
093}