package org.aperteworkflow.editor.stepeditor.user; import com.vaadin.Application; import org.aperteworkflow.editor.vaadin.GenericEditorApplication; import pl.net.bluesoft.rnd.processtool.plugins.ProcessToolRegistry; import pl.net.bluesoft.rnd.processtool.ui.widgets.ProcessToolWidget; import pl.net.bluesoft.rnd.processtool.ui.widgets.annotations.Permission; import pl.net.bluesoft.rnd.processtool.ui.widgets.annotations.PermissionsUsed; import pl.net.bluesoft.rnd.processtool.ui.widgets.annotations.WidgetGroup; import pl.net.bluesoft.rnd.util.i18n.I18NProvider; import pl.net.bluesoft.rnd.util.i18n.I18NSource; import pl.net.bluesoft.util.lang.Classes; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.net.URL; import java.util.*; public class WidgetInfoLoader { private static final String BUNDLE_DESC_PREFIX; private static Set<Permission> DEFAULT_PERMISSIONS; static { BUNDLE_DESC_PREFIX = "widget.bundle.desc."; DEFAULT_PERMISSIONS = new HashSet<Permission>(); Permission[] dp = (Permission[]) getDefaultValue(PermissionsUsed.class); if (dp != null) { DEFAULT_PERMISSIONS.addAll(Arrays.asList(dp)); } } // TODO consider moving to Classes in bluesoft-util private static Object getDefaultValue(Class<? extends Annotation> annotationType) { return getDefaultValue(annotationType, "value"); } private static Object getDefaultValue(Class<? extends Annotation> annotationType, String attributeName) { try { Method method = annotationType.getDeclaredMethod(attributeName, new Class[0]); return method.getDefaultValue(); } catch (Exception ex) { return null; } } public static Map<BundleItem, Collection<WidgetItem>> loadAvailableWidgets(Application application) throws ClassNotFoundException { ProcessToolRegistry reg = GenericEditorApplication.getRegistry(); I18NSource i18NSource = I18NSource.ThreadUtil.getThreadI18nSource(); Map<BundleItem, Collection<WidgetItem>> availableWidgets = new HashMap<BundleItem, Collection<WidgetItem>>(); Map<String, Class<? extends ProcessToolWidget>> registeredWidgets = reg.getAvailableWidgets(); if (registeredWidgets == null || registeredWidgets.size() == 0) { return availableWidgets; } // Widgets are available in registry by both @AliasName and their class name // we don't want to present each step twice so we exclude duplicates. Do note // that java.lang.Class does not override hashCode() and equals() so we use it's name Map<String, Class<? extends ProcessToolWidget>> viewableWidgets = new HashMap<String, Class<? extends ProcessToolWidget>>(); for (Class<? extends ProcessToolWidget> widgetClass : registeredWidgets.values()) { viewableWidgets.put(widgetClass.getName(), widgetClass); } // Create sorted structure of widgets by processing their annotations Map<String, List<Class<? extends ProcessToolWidget>>> sortedWidgets = new HashMap<String, List<Class<? extends ProcessToolWidget>>>(); for (Class<? extends ProcessToolWidget> widgetClass : viewableWidgets.values()) { String widgetGroupName = "unsorted"; WidgetGroup widgetGroup = Classes.getClassAnnotation(widgetClass, WidgetGroup.class); if (widgetGroup != null) { widgetGroupName = widgetGroup.value(); } List<Class<? extends ProcessToolWidget>> widgetGroupItems = sortedWidgets.get(widgetGroupName); if (widgetGroupItems == null) { widgetGroupItems = new ArrayList<Class<? extends ProcessToolWidget>>(); sortedWidgets.put(widgetGroupName, widgetGroupItems); } widgetGroupItems.add(widgetClass); } // Process the sorted structure to final form for (Map.Entry<String, List<Class<? extends ProcessToolWidget>>> e : sortedWidgets.entrySet()) { String bundleName = e.getKey(); String bundleDescriptionKey = BUNDLE_DESC_PREFIX + bundleName; BundleItem bundleItem = new BundleItem( bundleName, i18NSource.getMessage(bundleDescriptionKey), new ArrayList<I18NProvider>(), new ArrayList<URL>() ); Collection<WidgetItem> widgets = new ArrayList<WidgetItem>(); for (Class widgetClass : e.getValue()) { widgets.add(new WidgetItem(widgetClass,DEFAULT_PERMISSIONS,bundleItem)); } removeNulls(widgets); if (widgets.size() > 0) { availableWidgets.put(bundleItem, widgets); } } return availableWidgets; } private static void removeNulls(Collection<WidgetItem> widgets) { for (;;) { if (!widgets.remove(null)) { return; } } } }