
cz.wicketstuff.boss.flow.processor.ext.AnnotationFlowFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of boss-flow Show documentation
Show all versions of boss-flow Show documentation
Workflow control and configuration java framework
/*
* Et netera, http://boss.etnetera.cz - Copyright (C) 2012
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License (version 2.1) as published by the Free Software
* Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU Lesser General Public License for more details:
* http://www.gnu.org/licenses/lgpl-3.0.txt
*
*/
package cz.wicketstuff.boss.flow.processor.ext;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cz.wicketstuff.boss.flow.annotation.FlowConditionProcessor;
import cz.wicketstuff.boss.flow.annotation.FlowStateEvent;
import cz.wicketstuff.boss.flow.annotation.FlowStateValidation;
import cz.wicketstuff.boss.flow.annotation.FlowSwitchProcessorExpression;
import cz.wicketstuff.boss.flow.annotation.FlowTransitionEvent;
import cz.wicketstuff.boss.flow.model.IFlowCarter;
import cz.wicketstuff.boss.flow.processor.condition.CannotProcessConditionException;
import cz.wicketstuff.boss.flow.util.listener.FlowStateChangeListenerCollection;
import cz.wicketstuff.boss.flow.util.listener.FlowStateValidationListenerCollection;
import cz.wicketstuff.boss.flow.util.listener.FlowTransitionChangeListenerCollection;
import cz.wicketstuff.boss.flow.util.processor.FlowConditionStateProcessorCollection;
import cz.wicketstuff.boss.flow.util.processor.FlowSwitchStateProcessorCollection;
public class AnnotationFlowFactory {
protected static final Logger logger = LoggerFactory.getLogger(AnnotationFlowFactory.class);
public AnnotationFlowFactory() {
}
public FlowStateChangeListenerCollection newFlowStateChangeListenerCollection() {
return new FlowStateChangeListenerCollection();
}
public FlowStateChangeListenerCollection getStateChangeListeners(Object bean) throws FlowAnnotationException {
return getStateChangeListeners(bean, newFlowStateChangeListenerCollection());
}
public FlowStateChangeListenerCollection getStateChangeListeners(final Object bean, FlowStateChangeListenerCollection listeners) throws FlowAnnotationException {
for(final Method method : findMethodCandidates(bean, FlowStateEvent.class)) {
FlowStateEvent eventAnnotation = method.getAnnotation(FlowStateEvent.class);
if(logger.isDebugEnabled()) {
logger.debug("Adding annoted FlowStateEvent method '" + method.getName() + "' of bean '" + bean + "'");
}
listeners.add(new FilteredStateChangeListener(eventAnnotation.event(), "".equals(eventAnnotation.stateNameRegex()) ? null : eventAnnotation.stateNameRegex(), eventAnnotation.type(), eventAnnotation.priority()) {
private static final long serialVersionUID = 1L;
@Override
protected void onStateEntryFiltered(IFlowCarter flow) {
try {
method.invoke(bean, flow);
} catch ( IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
throw new IllegalStateException("Cannot invoke annoted method '" + method.getName() + "' of bean '" + bean + "' because: " + e.getMessage(), e);
}
}
@Override
protected void onStateLeavingFiltered(IFlowCarter flow) {
try {
method.invoke(bean, flow);
} catch ( IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
throw new IllegalStateException("Cannot invoke annoted method of bean '" + bean + "' because: " + e.getMessage(), e);
}
}
});
}
listeners.sort();
return listeners;
}
public FlowStateValidationListenerCollection newFlowStateValidationListenerCollection() {
return new FlowStateValidationListenerCollection();
}
public FlowStateValidationListenerCollection getStateValidationListeners(Object bean) throws FlowAnnotationException {
return getStateValidationListeners(bean, newFlowStateValidationListenerCollection());
}
public FlowStateValidationListenerCollection getStateValidationListeners(final Object bean, FlowStateValidationListenerCollection listeners) throws FlowAnnotationException {
for(final Method method : findMethodCandidates(bean, FlowStateValidation.class)) {
FlowStateValidation eventAnnotation = method.getAnnotation(FlowStateValidation.class);
if(logger.isDebugEnabled()) {
logger.debug("Adding annoted FlowStateValidation method '" + method.getName() + "' of bean '" + bean + "'");
}
listeners.add(new FilteredStateValidationListener(eventAnnotation.event(), "".equals(eventAnnotation.stateNameRegex()) ? null : eventAnnotation.stateNameRegex(), eventAnnotation.type(), eventAnnotation.priority()) {
private static final long serialVersionUID = 1L;
@Override
protected void onStateValidFiltered(IFlowCarter flow) {
try {
method.invoke(bean, flow);
} catch ( IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
throw new IllegalStateException("Cannot invoke annoted method '" + method.getName() + "' of bean '" + bean + "' because: " + e.getMessage(), e);
}
}
@Override
protected void onStateInvalidFiltered(IFlowCarter flow) {
try {
method.invoke(bean, flow);
} catch ( IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
throw new IllegalStateException("Cannot invoke annoted method '" + method.getName() + "' of bean '" + bean + "' because: " + e.getMessage(), e);
}
}
});
}
listeners.sort();
return listeners;
}
public FlowTransitionChangeListenerCollection newFlowTransitionChangeListenerCollection() {
return new FlowTransitionChangeListenerCollection();
}
public FlowTransitionChangeListenerCollection getTransitionChangeListeners(Object bean) throws FlowAnnotationException {
return getTransitionChangeListeners(bean, newFlowTransitionChangeListenerCollection());
}
public FlowTransitionChangeListenerCollection getTransitionChangeListeners(final Object bean, FlowTransitionChangeListenerCollection listeners) throws FlowAnnotationException {
for(final Method method : findMethodCandidates(bean, FlowTransitionEvent.class)) {
FlowTransitionEvent eventAnnotation = method.getAnnotation(FlowTransitionEvent.class);
if(logger.isDebugEnabled()) {
logger.debug("Adding annoted FlowTransitionEvent change listener method '" + method.getName() + "' of bean '" + bean + "'");
}
listeners.add(new FilteredTransitionChangeListener(eventAnnotation.event(), "".equals(eventAnnotation.transitionNameRegex()) ? null : eventAnnotation.transitionNameRegex(), eventAnnotation.priority()) {
private static final long serialVersionUID = 1L;
@Override
protected void onTransitionStartFiltered(IFlowCarter flow) {
try {
method.invoke(bean, flow);
} catch ( IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
throw new IllegalStateException("Cannot invoke annoted method '" + method.getName() + "' of bean '" + bean + "' because: " + e.getMessage(), e);
}
}
@Override
protected void onTransitionFinishedFiltered(IFlowCarter flow) {
try {
method.invoke(bean, flow);
} catch ( IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
throw new IllegalStateException("Cannot invoke annoted method '" + method.getName() + "' of bean '" + bean + "' because: " + e.getMessage(), e);
}
}
});
}
listeners.sort();
return listeners;
}
public FlowConditionStateProcessorCollection newFlowConditionStateCollection() {
return new FlowConditionStateProcessorCollection();
}
public FlowConditionStateProcessorCollection getFlowConditionProcessors(Object bean) throws FlowAnnotationException {
return getFlowConditionProcessors(bean, newFlowConditionStateCollection());
}
public FlowConditionStateProcessorCollection getFlowConditionProcessors(final Object bean, FlowConditionStateProcessorCollection processorCollection) throws FlowAnnotationException {
for(final Method method : findMethodConditionCandidates(bean, FlowConditionProcessor.class)) {
FlowConditionProcessor conditionAnnotation = method.getAnnotation(FlowConditionProcessor.class);
if(logger.isDebugEnabled()) {
logger.debug("Adding annoted FlowConditionProcessor method '" + method.getName() + "' of bean '" + bean + "'");
}
processorCollection.add(
new FilteredStateConditionProcessor(
"".equals(conditionAnnotation.conditionExpressionRegex()) ? null : conditionAnnotation.conditionExpressionRegex(),
"".equals(conditionAnnotation.stateNameRegex()) ? null : conditionAnnotation.stateNameRegex(),
conditionAnnotation.type()) {
private static final long serialVersionUID = 1L;
@Override
public boolean ifCondition(String conditionExpression,
IFlowCarter flow)
throws CannotProcessConditionException {
try {
return (boolean) method.invoke(bean, conditionExpression, flow);
} catch ( IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
throw new IllegalStateException("Cannot invoke annoted method '" + method.getName() + "', condition '" + conditionExpression + ", of bean " + bean + "' because: " + e.getMessage(), e);
}
}
});
}
return processorCollection;
}
public FlowSwitchStateProcessorCollection newFlowSwitchStateProcessorCollection() {
return new FlowSwitchStateProcessorCollection();
}
public FlowSwitchStateProcessorCollection getFlowSwitchProcessors(Object bean) throws FlowAnnotationException {
return getFlowSwitchProcessors(bean, newFlowSwitchStateProcessorCollection());
}
public FlowSwitchStateProcessorCollection getFlowSwitchProcessors(final Object bean, FlowSwitchStateProcessorCollection processorCollection) throws FlowAnnotationException {
for(final Method method : findMethodSwitchCandidates(bean, FlowSwitchProcessorExpression.class)) {
FlowSwitchProcessorExpression conditionAnnotation = method.getAnnotation(FlowSwitchProcessorExpression.class);
if(logger.isDebugEnabled()) {
logger.debug("Adding annoted FlowSwitchProcessorExpression method '" + method.getName() + "' of bean '" + bean + "'");
}
processorCollection.add(
new FilteredStateSwitchProcessor(
"".equals(conditionAnnotation.switchExpressionRegex()) ? null : conditionAnnotation.switchExpressionRegex(),
"".equals(conditionAnnotation.stateNameRegex()) ? null : conditionAnnotation.stateNameRegex(),
conditionAnnotation.type()) {
private static final long serialVersionUID = 1L;
@Override
public String resolveSwitchExpression(
IFlowCarter flow, String switchExpression) {
try {
return (String) method.invoke(bean, switchExpression, flow);
} catch ( IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
throw new IllegalStateException("Cannot invoke annoted method '" + method.getName() + "', condition '" + switchExpression + ", of bean '" + bean + "' because: " + e.getMessage(), e);
}
}
});
}
return processorCollection;
}
public List findMethodCandidates(Object bean, Class extends Annotation> annotation) throws FlowAnnotationException {
List list = new ArrayList();
for(final Method method : bean.getClass().getMethods()) {
if(method.isAnnotationPresent(annotation)) {
checkFlowMethod(method, bean);
list.add(method);
}
}
return list;
}
public List findMethodConditionCandidates(Object bean, Class extends Annotation> annotation) throws FlowAnnotationException {
List list = new ArrayList();
for(final Method method : bean.getClass().getMethods()) {
if(method.isAnnotationPresent(annotation)) {
checkConditionMethod(method, bean);
list.add(method);
}
}
return list;
}
public List findMethodSwitchCandidates(Object bean, Class extends Annotation> annotation) throws FlowAnnotationException {
List list = new ArrayList();
for(final Method method : bean.getClass().getMethods()) {
if(method.isAnnotationPresent(annotation)) {
checkSwitchMethod(method, bean);
list.add(method);
}
}
return list;
}
public void checkFlowMethod(Method method, Object bean) throws FlowAnnotationException {
Class>[] parameters = method.getParameterTypes();
if(parameters.length != 1) {
throw new FlowAnnotationException("The method '" + method.getName() + "' of bean '" + bean + "' has to have just one parameter, not more, not less!");
}
try {
if(parameters[0].asSubclass(IFlowCarter.class) == null) {
throw new FlowAnnotationException("The paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not a type of IFlowCarter!");
}
} catch (ClassCastException e) {
throw new FlowAnnotationException("The paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not a type of IFlowCarter!", e);
}
if(!Modifier.isPublic(method.getModifiers())) {
throw new FlowAnnotationException("The paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not public!");
}
}
public void checkConditionMethod(Method method, Object bean) throws FlowAnnotationException {
Class>[] parameters = method.getParameterTypes();
if(parameters.length != 2) {
throw new FlowAnnotationException("The method '" + method.getName() + "' of bean '" + bean + "' has to have just one parameter, not more, not less! Correct parameters are String, IFlowCarter");
}
try {
if(method.getReturnType().asSubclass(boolean.class) == null) {
throw new FlowAnnotationException("The return type of method '" + method.getName() + "' of bean '" + bean + "' is not a type of boolean!");
}
} catch (ClassCastException e) {
throw new FlowAnnotationException("The return type method '" + method.getName() + "' of bean '" + bean + "' is not a type of boolean!", e);
}
try {
if(parameters[0].asSubclass(String.class) == null) {
throw new FlowAnnotationException("The first paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not a type of String!");
}
} catch (ClassCastException e) {
throw new FlowAnnotationException("The first paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not a type of String!", e);
}
try {
if(parameters[1].asSubclass(IFlowCarter.class) == null) {
throw new FlowAnnotationException("The second paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not a type of IFlowCarter!");
}
} catch (ClassCastException e) {
throw new FlowAnnotationException("The second paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not a type of IFlowCarter!", e);
}
if(!Modifier.isPublic(method.getModifiers())) {
throw new FlowAnnotationException("The method '" + method.getName() + "' of bean '" + bean + "' is not public!");
}
}
public void checkSwitchMethod(Method method, Object bean) throws FlowAnnotationException {
Class>[] parameters = method.getParameterTypes();
if(parameters.length != 2) {
throw new FlowAnnotationException("The method '" + method.getName() + "' of bean '" + bean + "' has to have just one parameter, not more, not less! Correct parameters are String, IFlowCarter");
}
try {
if(method.getReturnType().asSubclass(String.class) == null) {
throw new FlowAnnotationException("The return type of method '" + method.getName() + "' of bean '" + bean + "' is not a type of String!");
}
} catch (ClassCastException e) {
throw new FlowAnnotationException("The return type method '" + method.getName() + "' of bean '" + bean + "' is not a type of boolean!", e);
}
try {
if(parameters[0].asSubclass(String.class) == null) {
throw new FlowAnnotationException("The first paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not a type of String!");
}
} catch (ClassCastException e) {
throw new FlowAnnotationException("The first paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not a type of String!", e);
}
try {
if(parameters[1].asSubclass(IFlowCarter.class) == null) {
throw new FlowAnnotationException("The second paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not a type of IFlowCarter!");
}
} catch (ClassCastException e) {
throw new FlowAnnotationException("The second paremeter of method '" + method.getName() + "' of bean '" + bean + "' is not a type of IFlowCarter!", e);
}
if(!Modifier.isPublic(method.getModifiers())) {
throw new FlowAnnotationException("The method '" + method.getName() + "' of bean '" + bean + "' is not public!");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy