/* * Copyright 2013 Nokia Solutions and Networks Oyj * * Licensed 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.robotframework.javalib.beans.annotation; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.robotframework.javalib.annotation.RobotKeyword; import org.robotframework.javalib.annotation.RobotKeywordOverload; import org.robotframework.javalib.keyword.DocumentedKeyword; import org.robotframework.javalib.reflection.IKeywordInvoker; import org.robotframework.javalib.reflection.KeywordInvoker; public class AnnotationKeywordExtractor implements IKeywordExtractor<DocumentedKeyword> { public Map<String, DocumentedKeyword> extractKeywords(final Object keywordBean) { Map<String, DocumentedKeyword> extractedKeywords = new HashMap<String, DocumentedKeyword>(); Method[] methods = keywordBean.getClass().getMethods(); for (final Method method : methods) { if (method.isAnnotationPresent(RobotKeyword.class) || method.isAnnotationPresent(RobotKeywordOverload.class)) { createOrAddKeyword(extractedKeywords, keywordBean, method); } } return extractedKeywords; } private void createOrAddKeyword(Map<String, DocumentedKeyword> extractedKeywords, Object keywordBean, Method method) { String name = method.getName(); if(extractedKeywords.containsKey(name)){ extractedKeywords.put(name, addPolymorphToKeywordDefinition(extractedKeywords.get(name), keywordBean, method)); }else{ extractedKeywords.put(name, createKeyword(keywordBean, method)); } } IKeywordInvoker createKeywordInvoker(Object keywordBean, Method method) { return new KeywordInvoker(keywordBean, method); } private DocumentedKeyword createKeyword(Object keywordBean, Method method) { IKeywordInvoker keywordInvoker = createKeywordInvoker(keywordBean, method); return createKeyword(keywordInvoker); } private DocumentedKeyword createKeyword(final IKeywordInvoker keywordInvoker) { return new DocumentedKeyword() { public Object execute(Object[] arguments) { return keywordInvoker.invoke(arguments); } public String[] getArgumentNames() { return keywordInvoker.getParameterNames(); } public String getDocumentation() { return keywordInvoker.getDocumentation(); } }; } private DocumentedKeyword addPolymorphToKeywordDefinition(final DocumentedKeyword original, final Object keywordBean, final Method method) { final DocumentedKeyword other = createKeyword(keywordBean, method); final boolean isOverload = method.isAnnotationPresent(RobotKeywordOverload.class); if(isOverload && method.isAnnotationPresent(RobotKeyword.class)) throw new AssertionError("Method definition should not have both RobotKeyword and RobotKeywordOverload annotations"); final int parameterTypesLength = method.getParameterTypes().length; return new DocumentedKeyword() { public Object execute(Object[] arguments) { if(parameterTypesLength == arguments.length){ return other.execute(arguments); } return original.execute(arguments); } public String[] getArgumentNames() { if(isOverload){ return original.getArgumentNames(); } return other.getArgumentNames(); } public String getDocumentation() { if(isOverload){ return original.getDocumentation(); } return other.getDocumentation(); } }; } }