catch up with development

Signed-off-by: Ralf Mollik <ramollik@compex-commerce.com>
diff --git a/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/annotations/EnumDefaultLiteral.java b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/annotations/EnumDefaultLiteral.java
new file mode 100644
index 0000000..4172c51
--- /dev/null
+++ b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/annotations/EnumDefaultLiteral.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0 
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *         Florian Pirchner - Initial implementation
+ */
+package org.eclipse.osbp.runtime.common.annotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target({ TYPE })
+@Retention(RUNTIME)
+public @interface EnumDefaultLiteral {
+
+	/**
+	 * The name of the EnumLiteral which should be used for default.
+	 * 
+	 * @return
+	 */
+	String literalName();
+
+}
diff --git a/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/annotations/StateClass.java b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/annotations/StateClass.java
new file mode 100644
index 0000000..0df53d3
--- /dev/null
+++ b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/annotations/StateClass.java
@@ -0,0 +1,13 @@
+package org.eclipse.osbp.runtime.common.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target(FIELD)
+public @interface StateClass {
+
+}
diff --git a/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/event/EventDispatcherEvent.java b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/event/EventDispatcherEvent.java
index 58621ce..f8df133 100644
--- a/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/event/EventDispatcherEvent.java
+++ b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/event/EventDispatcherEvent.java
@@ -15,6 +15,7 @@
  */
 package org.eclipse.osbp.runtime.common.event;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -53,7 +54,9 @@
 		/** Answer is ok. */
 		OK,
 		/** show bpmn. */
-		BPMN
+		BPMN,
+		/** a state class attribute changed. */
+		STATE_CLASS_CHANGE
 	}
 
 	/**
@@ -170,7 +173,11 @@
 			if(!data.containsKey(EventDispatcherDataTag.LIST)) {
 				data.put(EventDispatcherDataTag.LIST, new CopyOnWriteArrayList<String>());
 			}
-			((List<String>)data.get(EventDispatcherDataTag.LIST)).add((String)item);
+			if(item instanceof Collection) {
+				((List<String>)data.get(EventDispatcherDataTag.LIST)).addAll((Collection<? extends String>) item);
+			} else if(item instanceof String) {
+				((List<String>)data.get(EventDispatcherDataTag.LIST)).add((String)item);
+			}
 		} else {
 			data.put(tag, item);
 		}
diff --git a/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/event/SelectionStore.java b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/event/SelectionStore.java
index 65f3aca..019c90a 100644
--- a/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/event/SelectionStore.java
+++ b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/event/SelectionStore.java
@@ -9,11 +9,17 @@
 import org.eclipse.e4.ui.model.application.ui.MUIElement;
 import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class SelectionStore {
+	/** The Constant log. */
+	protected static final Logger log = LoggerFactory.getLogger(SelectionStore.class.getName());
+	
 	private Map<String, Object> selections = new HashMap<>();
 	
 	public void setSelection(String fqn, Object id) {
+		log.debug("setSelection({},{})",fqn,id);
 		if(id != null) {
 			selections.put(fqn, id);
 		} else {
@@ -23,6 +29,7 @@
 	
 	public Object getSelection(String fqn) {
 		if(selections.containsKey(fqn)) {
+			if( log.isDebugEnabled() ) log.debug("getSelection({}) = {}",fqn,selections.get(fqn));
 			return selections.get(fqn);
 		}
 		return null;
@@ -30,8 +37,10 @@
 	
 	@SuppressWarnings("unchecked")
 	private void addSelection(String fqn, Object id) {
+		log.debug("addSelection({},{})",fqn,id);		
 		if(!selections.containsKey(fqn) || !(selections.get(fqn) instanceof List<?>)) {
-			selections.put(fqn, new ArrayList<Object>());
+			log.debug("    as new ... ");
+			selections.put(fqn, new ArrayList<>());
 		}
 		((List<Object>)selections.get(fqn)).add(id);
 	}
@@ -41,6 +50,7 @@
 		if(selections.containsKey(fqn) && selections.get(fqn) instanceof List<?>) {
 			((List<Object>)selections.get(fqn)).remove(id);
 			if(((List<Object>)selections.get(fqn)).isEmpty()) {
+				log.debug("removeSelection({},{})",fqn,id);
 				selections.remove(fqn);
 			}
 		}
@@ -52,6 +62,7 @@
 			element = element.getParent();
 		}
 		if(element != null) {
+			if( log.isDebugEnabled() ) log.debug("getContext() returns {}",((MPerspective)element).getContext().toString());
 			return ((MPerspective)element).getContext(); 
 		}
 		return null;
diff --git a/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/filter/IStateClassService.java b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/filter/IStateClassService.java
new file mode 100644
index 0000000..596e1da
--- /dev/null
+++ b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/filter/IStateClassService.java
@@ -0,0 +1,7 @@
+package org.eclipse.osbp.runtime.common.filter;
+
+public interface IStateClassService {
+	void nextState(Object dto);
+	void previousState(Object dto);
+	Long numberOfStates(Object state);
+}
diff --git a/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/util/BeanUtils.java b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/util/BeanUtils.java
index c98c9f4..1d9a5db 100644
--- a/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/util/BeanUtils.java
+++ b/org.eclipse.osbp.runtime.common/src/org/eclipse/osbp/runtime/common/util/BeanUtils.java
@@ -23,6 +23,7 @@
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -40,6 +41,7 @@
 import org.eclipse.osbp.runtime.common.annotations.HistorizedObject;
 import org.eclipse.osbp.runtime.common.annotations.OnKanbanCard;
 import org.eclipse.osbp.runtime.common.annotations.Range;
+import org.eclipse.osbp.runtime.common.annotations.StateClass;
 import org.eclipse.osbp.runtime.common.annotations.UpdateAt;
 import org.eclipse.osbp.runtime.common.annotations.UpdateBy;
 import org.slf4j.Logger;
@@ -50,6 +52,10 @@
 	/** The Constant LOGGER. */
 	private static final Logger LOGGER = LoggerFactory.getLogger(BeanUtils.class);
 
+	private static Map<Class<?>, Set<String>> stateClassAttributes = Collections.synchronizedMap(new HashMap<>());
+
+	private static Map<Class<?>, Set<String>> stateClassNames = Collections.synchronizedMap(new HashMap<>());
+
 	public static List<Field> getAllFilteringFields(Class<?> clazz) {
 		List<Field> result = new ArrayList<>();
 
@@ -61,7 +67,7 @@
 
 		return result;
 	}
-	
+
 	public static List<Field> getAllFields(Class<?> clazz, Class<? extends Annotation> annotation) {
 		List<Field> result = new ArrayList<>();
 
@@ -73,7 +79,7 @@
 
 		return result;
 	}
-	
+
 	/**
 	 * Returns a single field for the class and annotation.
 	 * 
@@ -81,7 +87,8 @@
 	 * @param annotation
 	 * @return
 	 *
-	 *@throws IllegalStateException if more then 1 field found
+	 * @throws IllegalStateException
+	 *             if more then 1 field found
 	 */
 	public static Field getField(Class<?> clazz, Class<? extends Annotation> annotation) {
 		List<Field> result = new ArrayList<>();
@@ -91,8 +98,8 @@
 				result.add(field);
 			}
 		}
-		
-		if(result.size() > 1) {
+
+		if (result.size() > 1) {
 			throw new IllegalStateException("More then one field found with given annotation " + annotation);
 		}
 
@@ -226,8 +233,8 @@
 			return null;
 		}
 
-		return getAllFields(clazz).stream().filter(f -> f.isAnnotationPresent(OnKanbanCard.class))
-				.map(f -> f.getName()).collect(Collectors.toList());
+		return getAllFields(clazz).stream().filter(f -> f.isAnnotationPresent(OnKanbanCard.class)).map(f -> f.getName())
+				.collect(Collectors.toList());
 	}
 
 	/**
@@ -320,33 +327,34 @@
 		}
 		return field.isAnnotationPresent(annotation);
 	}
-	
+
 	/**
 	 * Returns true, if {@link HistorizedObject} annotation is present.
+	 * 
 	 * @param clazz
 	 * @return
 	 */
 	public static boolean isHistorized(Class<?> clazz) {
 		Class<?> type = clazz;
-		while(type != null) {
-			if(type.isAnnotationPresent(HistorizedObject.class)){
+		while (type != null) {
+			if (type.isAnnotationPresent(HistorizedObject.class)) {
 				return true;
 			}
 			type = type.getSuperclass();
 		}
 		return false;
 	}
-	
-	public static void setCreateUser(Object bean, String user){
+
+	public static void setCreateUser(Object bean, String user) {
 		List<Field> fields = getAllFields(bean.getClass(), CreateBy.class);
-		for(Field field : fields) {
+		for (Field field : fields) {
 			setter(bean, user, field);
 		}
 	}
-	
-	public static void setUpdateUser(Object bean, String user){
+
+	public static void setUpdateUser(Object bean, String user) {
 		List<Field> fields = getAllFields(bean.getClass(), UpdateBy.class);
-		for(Field field : fields) {
+		for (Field field : fields) {
 			setter(bean, user, field);
 		}
 	}
@@ -361,67 +369,55 @@
 					break;
 				}
 			}
-		} catch (IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+		} catch (IntrospectionException | IllegalAccessException | IllegalArgumentException
+				| InvocationTargetException e) {
 			LOGGER.error("{}", e);
 		}
 	}
-	
-	public static void setCreateAt(Object bean, Date date){
+
+	public static void setCreateAt(Object bean, Date date) {
 		List<Field> fields = getAllFields(bean.getClass(), CreateAt.class);
-		for(Field field : fields) {
-			setter(bean, date, field);
-		}
-	}
-	
-	public static void setUpdateAt(Object bean, Date date){
-		List<Field> fields = getAllFields(bean.getClass(), UpdateAt.class);
-		for(Field field : fields) {
+		for (Field field : fields) {
 			setter(bean, date, field);
 		}
 	}
 
-	public static String getCreateUser(Object bean){
-		List<Field> fields = getAllFields(bean.getClass(), CreateBy.class);
-		for(Field field : fields) {
-			try {
-				field.setAccessible(true);
-				return (String)field.get(bean);
-			} catch (IllegalArgumentException | IllegalAccessException e) {
-				LOGGER.error("{}", e);
-			}
-		}
-		return null;
-	}
-	
-	public static String getUpdateUser(Object bean){
-		List<Field> fields = getAllFields(bean.getClass(), UpdateBy.class);
-		for(Field field : fields) {
-			try {
-				field.setAccessible(true);
-				return (String)field.get(bean);
-			} catch (IllegalArgumentException | IllegalAccessException e) {
-				LOGGER.error("{}", e);
-			}
-		}
-		return null;
-	}
-	
-	public static Date getCreateAt(Object bean){
-		List<Field> fields = getAllFields(bean.getClass(), CreateAt.class);
-		for(Field field : fields) {
-			try {
-				field.setAccessible(true);
-				return (Date)field.get(bean);
-			} catch (IllegalArgumentException | IllegalAccessException e) {
-				LOGGER.error("{}", e);
-			}
-		}
-		return null;
-	}
-	
-	public static Date getUpdateAt(Object bean){
+	public static void setUpdateAt(Object bean, Date date) {
 		List<Field> fields = getAllFields(bean.getClass(), UpdateAt.class);
-		for(Field field : fields) {
+		for (Field field : fields) {
+			setter(bean, date, field);
+		}
+	}
+
+	public static String getCreateUser(Object bean) {
+		List<Field> fields = getAllFields(bean.getClass(), CreateBy.class);
+		for (Field field : fields) {
+			try {
+				field.setAccessible(true);
+				return (String) field.get(bean);
+			} catch (IllegalArgumentException | IllegalAccessException e) {
+				LOGGER.error("{}", e);
+			}
+		}
+		return null;
+	}
+
+	public static String getUpdateUser(Object bean) {
+		List<Field> fields = getAllFields(bean.getClass(), UpdateBy.class);
+		for (Field field : fields) {
+			try {
+				field.setAccessible(true);
+				return (String) field.get(bean);
+			} catch (IllegalArgumentException | IllegalAccessException e) {
+				LOGGER.error("{}", e);
+			}
+		}
+		return null;
+	}
+
+	public static Date getCreateAt(Object bean) {
+		List<Field> fields = getAllFields(bean.getClass(), CreateAt.class);
+		for (Field field : fields) {
 			try {
 				field.setAccessible(true);
 				return (Date) field.get(bean);
@@ -431,4 +427,53 @@
 		}
 		return null;
 	}
+
+	public static Date getUpdateAt(Object bean) {
+		List<Field> fields = getAllFields(bean.getClass(), UpdateAt.class);
+		for (Field field : fields) {
+			try {
+				field.setAccessible(true);
+				return (Date) field.get(bean);
+			} catch (IllegalArgumentException | IllegalAccessException e) {
+				LOGGER.error("{}", e);
+			}
+		}
+		return null;
+	}
+
+	public static Set<String> getStateClassAttributes(Class<?> clazz) {
+
+		if (stateClassAttributes.containsKey(clazz)) {
+			return stateClassAttributes.get(clazz);
+		}
+
+		Set<String> result = new HashSet<>();
+		for (Field field : getAllFields(clazz)) {
+			if (field.isAnnotationPresent(StateClass.class)) {
+				result.add(field.getName());
+			}
+		}
+
+		stateClassAttributes.put(clazz, result);
+
+		return result;
+	}
+
+	public static Set<String> getStateClassNames(Class<?> clazz) {
+		
+		if (stateClassNames.containsKey(clazz)) {
+			return stateClassNames.get(clazz);
+		}
+		
+		Set<String> result = new HashSet<>();
+		for (Field field : getAllFields(clazz)) {
+			if (field.isAnnotationPresent(StateClass.class)) {
+				result.add(field.getType().getCanonicalName());
+			}
+		}
+		
+		stateClassNames.put(clazz, result);
+		
+		return result;
+	}
 }