/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.karaf.shell.commands.meta; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.felix.gogo.commands.Action; import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; import org.apache.karaf.shell.commands.Option; public class ActionMetaDataFactory { public ActionMetaData create(Class<? extends Action> actionClass) { Command command = getCommand(actionClass); Map<Option, Field> options = new HashMap<Option, Field>(); Map<Argument, Field> arguments = new HashMap<Argument, Field>(); List<Argument> orderedArguments = new ArrayList<Argument>(); for (Class<?> type = actionClass; type != null; type = type.getSuperclass()) { for (Field field : type.getDeclaredFields()) { Option option = field.getAnnotation(Option.class); if (option == null) { option = getAndConvertDeprecatedOption(field); } if (option != null) { options.put(option, field); } Argument argument = field.getAnnotation(Argument.class); if (argument == null) { argument = getAndConvertDeprecatedArgument(field); } if (argument != null) { argument = replaceDefaultArgument(field, argument); arguments.put(argument, field); int index = argument.index(); while (orderedArguments.size() <= index) { orderedArguments.add(null); } if (orderedArguments.get(index) != null) { throw new IllegalArgumentException("Duplicate argument index: " + index + " on Action " + actionClass.getName()); } orderedArguments.set(index, argument); } } } assertIndexesAreCorrect(actionClass, orderedArguments); return new ActionMetaData(actionClass, command, options, arguments, orderedArguments, null); } public Command getCommand(Class<? extends Action> actionClass) { Command command = actionClass.getAnnotation(Command.class); if (command == null) { command = getAndConvertDeprecatedCommand(actionClass); } return command; } @SuppressWarnings("deprecation") public Command getAndConvertDeprecatedCommand(Class<? extends Action> actionClass) { final org.apache.felix.gogo.commands.Command oldCommand = actionClass.getAnnotation(org.apache.felix.gogo.commands.Command.class); if (oldCommand == null) { return null; } return new Command() { @Override public Class<? extends Annotation> annotationType() { return Command.class; } @Override public String scope() { return oldCommand.scope(); } @Override public String name() { return oldCommand.name(); } @Override public String detailedDescription() { return oldCommand.detailedDescription(); } @Override public String description() { return oldCommand.description(); } }; } @SuppressWarnings("deprecation") private Option getAndConvertDeprecatedOption(Field field) { final org.apache.felix.gogo.commands.Option oldOption = field.getAnnotation(org.apache.felix.gogo.commands.Option.class); if (oldOption == null) { return null; } return new Option() { @Override public Class<? extends Annotation> annotationType() { return Option.class; } @Override public String valueToShowInHelp() { return oldOption.valueToShowInHelp(); } @Override public boolean required() { return oldOption.required(); } @Override public String name() { return oldOption.name(); } @Override public boolean multiValued() { return oldOption.multiValued(); } @Override public String description() { return oldOption.description(); } @Override public String[] aliases() { return oldOption.aliases(); } }; } @SuppressWarnings("deprecation") private Argument getAndConvertDeprecatedArgument(Field field) { final org.apache.felix.gogo.commands.Argument oldArgument = field.getAnnotation(org.apache.felix.gogo.commands.Argument.class); if (oldArgument == null) { return null; } return new Argument() { @Override public Class<? extends Annotation> annotationType() { return Argument.class; } @Override public String valueToShowInHelp() { return oldArgument.valueToShowInHelp(); } @Override public boolean required() { return oldArgument.required(); } @Override public String name() { return oldArgument.name(); } @Override public boolean multiValued() { return oldArgument.multiValued(); } @Override public int index() { return oldArgument.index(); } @Override public String description() { return oldArgument.description(); } }; } private Argument replaceDefaultArgument(Field field, Argument argument) { if (Argument.DEFAULT.equals(argument.name())) { final Argument delegate = argument; final String name = field.getName(); argument = new Argument() { public String name() { return name; } public String description() { return delegate.description(); } public boolean required() { return delegate.required(); } public int index() { return delegate.index(); } public boolean multiValued() { return delegate.multiValued(); } public String valueToShowInHelp() { return delegate.valueToShowInHelp(); } public Class<? extends Annotation> annotationType() { return delegate.annotationType(); } }; } return argument; } private void assertIndexesAreCorrect(Class<? extends Action> actionClass, List<Argument> orderedArguments) { for (int i = 0; i < orderedArguments.size(); i++) { if (orderedArguments.get(i) == null) { throw new IllegalArgumentException("Missing argument for index: " + i + " on Action " + actionClass.getName()); } } } }