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
020package org.crsh.cli.impl.invocation;
021
022import org.crsh.cli.descriptor.CommandDescriptor;
023import org.crsh.cli.descriptor.OptionDescriptor;
024import org.crsh.cli.descriptor.ParameterDescriptor;
025import org.crsh.cli.impl.SyntaxException;
026
027import java.util.Collection;
028import java.util.Collections;
029import java.util.LinkedHashMap;
030import java.util.LinkedList;
031import java.util.List;
032import java.util.Map;
033
034/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
035public final class InvocationMatch<T> {
036
037  /** . */
038  private final CommandDescriptor<T> descriptor;
039
040  /** . */
041  private Map<OptionDescriptor, OptionMatch> options;
042
043  /** . */
044  private List<ArgumentMatch> arguments;
045
046  /** . */
047  private String rest;
048
049  /** . */
050  private final InvocationMatch<T> owner;
051
052  public InvocationMatch(CommandDescriptor<T> descriptor) {
053    this(null, descriptor);
054  }
055
056  private InvocationMatch(InvocationMatch<T> owner, CommandDescriptor<T> descriptor) {
057    this.owner = owner;
058    this.descriptor = descriptor;
059    this.options = Collections.emptyMap();
060    this.rest = null;
061    this.arguments = Collections.emptyList();
062  }
063
064  public InvocationMatch<T> owner() {
065    return owner;
066  }
067
068  public InvocationMatch<T> subordinate(String name) {
069    CommandDescriptor<T> subordinate = descriptor.getSubordinate(name);
070    if (subordinate != null) {
071      return new InvocationMatch<T>(this, subordinate);
072    } else {
073      return null;
074    }
075  }
076
077  public CommandDescriptor<T> getDescriptor() {
078    return descriptor;
079  }
080
081  public final <D extends ParameterDescriptor> ParameterMatch<D> getParameter(D parameter) {
082    if (parameter instanceof OptionDescriptor) {
083      return (ParameterMatch<D>)options.get(parameter);
084    } else {
085      for (ArgumentMatch argumentMatch : arguments) {
086        if (argumentMatch.getParameter()  == parameter) {
087          return (ParameterMatch<D>)argumentMatch;
088        }
089      }
090      return null;
091    }
092  }
093
094  public CommandInvoker<T, ?> getInvoker() {
095    return descriptor.getInvoker(this);
096  }
097
098  public Object invoke(T command) throws InvocationException, SyntaxException {
099    CommandInvoker<T, ?> invoker = getInvoker();
100    if (invoker != null) {
101      return invoker.invoke(command);
102    } else {
103      return null;
104    }
105  }
106
107  public Collection<OptionMatch> options() {
108    return options.values();
109  }
110
111  public void option(OptionMatch option) {
112    if (options.isEmpty()) {
113      options = new LinkedHashMap<OptionDescriptor, OptionMatch>();
114    }
115    options.put(option.getParameter(), option);
116  }
117
118  public Collection<ArgumentMatch> arguments() {
119    return arguments;
120  }
121
122  public void argument(ArgumentMatch argument) {
123    if (arguments.isEmpty()) {
124      arguments = new LinkedList<ArgumentMatch>();
125    }
126    arguments.add(argument);
127  }
128
129  public String getRest() {
130    return rest;
131  }
132
133  public void setRest(String rest) {
134    this.rest = rest;
135  }
136}