/*
* Copyright (c) 2012. JSpringBot. All Rights Reserved.
*
* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The JSpringBot 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.jspringbot.spring;
import org.jspringbot.*;
import org.jspringbot.argument.ArgumentHandlerManager;
import org.jspringbot.keyword.main.SoftAssertManager;
import org.jspringbot.lifecycle.LifeCycleHandlerManager;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.HashMap;
import java.util.Map;
/**
* Robot Library that uses Spring application context.
*
* Searches keywords by looking for classes implementing the {@link org.jspringbot.Keyword} interface.
* Keyword information (name, documentation and parameter description) are acquired from
* {@link org.jspringbot.KeywordInfo} annotation on keyword implementations. In the absence of keyword information,
* keyword name is equivalent to bean name while keyword documentation and parameter description becomes "" and {"*args"}
* respectively.
*/
public class SpringRobotLibrary implements DynamicRobotLibrary {
private static final JSpringBotLogger LOGGER = JSpringBotLogger.getLogger(SpringRobotLibrary.class);
/** Spring application context. */
private ClassPathXmlApplicationContext context;
/** Mapping of keyword name to spring bean name. */
private Map<String, String> keywordToBeanMap;
private ArgumentHandlerManager argumentHandlers;
/**
* Create new SpringRobotLibrary object using the given configuration.
*
* @param springConfigPath String configuration path
* @throws Exception on error
*/
public SpringRobotLibrary(String springConfigPath) throws Exception {
context = ApplicationContextFactory.create(springConfigPath);
if(MainContextHolder.isEnabled()) {
SpringRobotLibraryManager manager = MainContextHolder.get().getBean(SpringRobotLibraryManager.class);
manager.addLibrary(getClass(), context);
}
argumentHandlers = new ArgumentHandlerManager(context);
keywordToBeanMap = KeywordUtils.getKeywordMap(context);
}
/**
* Implements the Robot Framework interface method 'get_keyword_names' required for dynamic libraries.
* Retrieve keyword names from the spring context by searching for classes implementing the
* {@link org.jspringbot.Keyword} interface.
*
* @return String array containing all keyword names defined in the context.
*/
public String[] getKeywordNames() {
return keywordToBeanMap.keySet().toArray(new String[keywordToBeanMap.size()]);
}
private void startJSpringBotKeyword(final String name, final Map attributes) {
SpringRobotLibraryManager manager = MainContextHolder.get().getBean(SpringRobotLibraryManager.class);
manager.visitActive(RobotScope.ALL, new Visitor<ClassPathXmlApplicationContext>() {
@Override
public void visit(ClassPathXmlApplicationContext context) {
new LifeCycleHandlerManager(context).startJSpringBotKeyword(name, attributes);
}
});
}
private void endJSpringBotKeyword(final String name, final Map attributes) {
SpringRobotLibraryManager manager = MainContextHolder.get().getBean(SpringRobotLibraryManager.class);
manager.visitActive(RobotScope.ALL, new Visitor<ClassPathXmlApplicationContext>() {
@Override
public void visit(ClassPathXmlApplicationContext context) {
new LifeCycleHandlerManager(context).endJSpringBotKeyword(name, attributes);
}
});
}
/**
* Implements the Robot Framework interface method 'run_keyword' required for dynamic libraries.
*
* @param keyword name of keyword to be executed
* @param params parameters passed by Robot Framework
* @return result of the keyword execution
*/
@SuppressWarnings("unchecked")
public Object runKeyword(String keyword, final Object[] params) {
Map attributes = new HashMap();
attributes.put("args", params);
try {
ApplicationContextHolder.set(context);
startJSpringBotKeyword(keyword, attributes);
Object[] handledParams = argumentHandlers.handlerArguments(keyword, params);
Object returnedValue = ((Keyword) context.getBean(keywordToBeanMap.get(keyword))).execute(handledParams);
attributes.put("status", "PASS");
return returnedValue;
} catch(Exception e) {
attributes.put("exception", e);
attributes.put("status", "FAIL");
if(SoftAssertManager.INSTANCE.isEnable()) {
LOGGER.warn("[SOFT ASSERT]: (" + keyword + ") -> " + e.getMessage());
SoftAssertManager.INSTANCE.add(keyword, e);
return null;
} else {
throw new IllegalStateException(e.getMessage(), e);
}
} finally {
endJSpringBotKeyword(keyword, attributes);
ApplicationContextHolder.remove();
}
}
/**
* Retrieves the documentation for the given keyword.
*
* @param keyword robot keyword
* @return keyword description
*/
public String getKeywordDocumentation(String keyword) {
return KeywordUtils.getDescription(keyword, context, keywordToBeanMap);
}
/**
* Retrieves parameter description for the given keyword.
*
* @param keyword robot keyword
* @return parameter description
*/
public String[] getKeywordArguments(String keyword) {
return KeywordUtils.getParameters(keyword, context, keywordToBeanMap);
}
}