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.cli.impl.lang; 021 022 import org.crsh.cli.descriptor.CommandDescriptor; 023 import org.crsh.cli.descriptor.Description; 024 import org.crsh.cli.impl.descriptor.IntrospectionException; 025 import org.crsh.cli.descriptor.OptionDescriptor; 026 import org.crsh.cli.descriptor.ParameterDescriptor; 027 import org.crsh.cli.impl.SyntaxException; 028 import org.crsh.cli.impl.invocation.InvocationException; 029 import org.crsh.cli.impl.invocation.InvocationMatch; 030 031 import java.lang.reflect.Type; 032 import java.util.HashSet; 033 import java.util.Map; 034 import java.util.Set; 035 036 class ClassDescriptor<T> extends ObjectCommandDescriptor<T> { 037 038 /** . */ 039 private final Class<T> type; 040 041 /** . */ 042 private final Map<String, MethodDescriptor<T>> methods; 043 044 ClassDescriptor(Class<T> type, String name, Map<String, MethodDescriptor<T>> methods, Description info) throws IntrospectionException { 045 super(name, info); 046 047 // 048 this.methods = methods; 049 this.type = type; 050 } 051 052 @Override 053 protected void addParameter(ParameterDescriptor parameter) throws IntrospectionException { 054 055 // Check we can add the option 056 if (parameter instanceof OptionDescriptor) { 057 OptionDescriptor option = (OptionDescriptor)parameter; 058 Set<String> blah = new HashSet<String>(); 059 for (String optionName : option.getNames()) { 060 blah.add((optionName.length() == 1 ? "-" : "--") + optionName); 061 } 062 for (MethodDescriptor<T> method : methods.values()) { 063 Set<String> diff = new HashSet<String>(method.getOptionNames()); 064 diff.retainAll(blah); 065 if (diff.size() > 0) { 066 throw new IntrospectionException("Cannot add method " + method.getName() + " because it has common " 067 + " options with its class: " + diff); 068 } 069 } 070 } 071 072 // 073 super.addParameter(parameter); 074 } 075 076 @Override 077 public ObjectCommandInvoker<T, ?> getInvoker(final InvocationMatch<Instance<T>> match) { 078 079 if (Runnable.class.isAssignableFrom(type)) { 080 return new ObjectCommandInvoker<T, Void>(match) { 081 @Override 082 public Class<Void> getReturnType() { 083 return Void.class; 084 } 085 @Override 086 public Type getGenericReturnType() { 087 return Void.class; 088 } 089 @Override 090 public Class<?>[] getParameterTypes() { 091 return new Class<?>[0]; 092 } 093 @Override 094 public Type[] getGenericParameterTypes() { 095 return new Type[0]; 096 } 097 public Void invoke(Instance<T> commandInstance) throws InvocationException, SyntaxException { 098 T command; 099 try { 100 command = commandInstance.get(); 101 } 102 catch (Exception e) { 103 throw new InvocationException(e); 104 } 105 MethodDescriptor.bind(match, getParameters(), command, Util.EMPTY_ARGS); 106 Runnable runnable = Runnable.class.cast(command); 107 try { 108 runnable.run(); 109 } 110 catch (Exception e) { 111 throw new InvocationException(e); 112 } 113 return null; 114 } 115 }; 116 } else { 117 return null; 118 } 119 } 120 121 @Override 122 public CommandDescriptor<Instance<T>> getOwner() { 123 return null; 124 } 125 126 @Override 127 public Map<String, ? extends MethodDescriptor<T>> getSubordinates() { 128 return methods; 129 } 130 131 }